summaryrefslogtreecommitdiff
path: root/mirrors
diff options
context:
space:
mode:
Diffstat (limited to 'mirrors')
-rw-r--r--mirrors/admin.py20
-rw-r--r--mirrors/management/commands/mirrorcheck.py17
-rw-r--r--mirrors/management/commands/mirrorresolv.py11
-rw-r--r--mirrors/models.py40
-rw-r--r--mirrors/urls.py10
-rw-r--r--mirrors/urls_mirrorlist.py12
6 files changed, 87 insertions, 23 deletions
diff --git a/mirrors/admin.py b/mirrors/admin.py
index 6990cca2..b9c2876a 100644
--- a/mirrors/admin.py
+++ b/mirrors/admin.py
@@ -1,4 +1,5 @@
import re
+from urlparse import urlparse, urlunsplit
from django import forms
from django.contrib import admin
@@ -9,15 +10,26 @@ class MirrorUrlForm(forms.ModelForm):
class Meta:
model = MirrorUrl
def clean_url(self):
+ # is this a valid-looking URL?
+ url_parts = urlparse(self.cleaned_data["url"])
+ if not url_parts.scheme:
+ raise forms.ValidationError("No URL scheme (protocol) provided.")
+ if not url_parts.netloc:
+ raise forms.ValidationError("No URL host provided.")
+ if url_parts.params or url_parts.query or url_parts.fragment:
+ raise forms.ValidationError(
+ "URL parameters, query, and fragment elements are not supported.")
# ensure we always save the URL with a trailing slash
- url = self.cleaned_data["url"].strip()
- if url[-1] == '/':
- return url
- return url + '/'
+ path = url_parts.path
+ if not path.endswith('/'):
+ path += '/'
+ url = urlunsplit((url_parts.scheme, url_parts.netloc, path, '', ''))
+ return url
class MirrorUrlInlineAdmin(admin.TabularInline):
model = MirrorUrl
form = MirrorUrlForm
+ readonly_fields = ('protocol', 'has_ipv4', 'has_ipv6')
extra = 3
# ripped off from django.forms.fields, adding netmask ability
diff --git a/mirrors/management/commands/mirrorcheck.py b/mirrors/management/commands/mirrorcheck.py
index 44d2b364..51be71ea 100644
--- a/mirrors/management/commands/mirrorcheck.py
+++ b/mirrors/management/commands/mirrorcheck.py
@@ -10,7 +10,9 @@ Usage: ./manage.py mirrorcheck
"""
from django.core.management.base import NoArgsCommand
+from django.db import transaction
+from collections import deque
from datetime import datetime, timedelta
import logging
import re
@@ -130,7 +132,7 @@ def mirror_url_worker(work, output):
item = work.get(block=False)
try:
log = check_mirror_url(item)
- output.put(log)
+ output.append(log)
finally:
work.task_done()
except Empty:
@@ -139,7 +141,7 @@ def mirror_url_worker(work, output):
class MirrorCheckPool(object):
def __init__(self, work, num_threads=10):
self.tasks = Queue()
- self.logs = Queue()
+ self.logs = deque()
for i in list(work):
self.tasks.put(i)
self.threads = []
@@ -149,6 +151,7 @@ class MirrorCheckPool(object):
thread.daemon = True
self.threads.append(thread)
+ @transaction.commit_on_success
def run(self):
logger.debug("starting threads")
for t in self.threads:
@@ -156,13 +159,9 @@ class MirrorCheckPool(object):
logger.debug("joining on all threads")
self.tasks.join()
logger.debug("processing log entries")
- try:
- while True:
- log = self.logs.get(block=False)
- log.save()
- self.logs.task_done()
- except Empty:
- logger.debug("all log items saved to database")
+ for log in self.logs:
+ log.save()
+ logger.debug("log entries saved")
def check_current_mirrors():
urls = MirrorUrl.objects.filter(
diff --git a/mirrors/management/commands/mirrorresolv.py b/mirrors/management/commands/mirrorresolv.py
index 8cbd51a3..8a628bd4 100644
--- a/mirrors/management/commands/mirrorresolv.py
+++ b/mirrors/management/commands/mirrorresolv.py
@@ -12,7 +12,6 @@ from django.core.management.base import NoArgsCommand
import sys
import logging
-from urlparse import urlparse
import socket
from mirrors.models import MirrorUrl
@@ -42,15 +41,13 @@ def resolve_mirrors():
logger.debug("requesting list of mirror URLs")
for mirrorurl in MirrorUrl.objects.filter(mirror__active=True):
try:
- hostname = urlparse(mirrorurl.url).hostname
- logger.debug("resolving %3i (%s)", mirrorurl.id, hostname)
- info = socket.getaddrinfo(hostname, None, 0, socket.SOCK_STREAM)
- families = [x[0] for x in info]
+ logger.debug("resolving %3i (%s)", mirrorurl.id, mirrorurl.hostname)
+ families = mirrorurl.address_families()
mirrorurl.has_ipv4 = socket.AF_INET in families
mirrorurl.has_ipv6 = socket.AF_INET6 in families
- logger.debug("%s: v4: %s v6: %s", hostname,
+ logger.debug("%s: v4: %s v6: %s", mirrorurl.hostname,
mirrorurl.has_ipv4, mirrorurl.has_ipv6)
- mirrorurl.save()
+ mirrorurl.save(force_update=True)
except socket.error, e:
logger.warn("error resolving %s: %s", hostname, e)
diff --git a/mirrors/models.py b/mirrors/models.py
index e070b1cd..401821a8 100644
--- a/mirrors/models.py
+++ b/mirrors/models.py
@@ -1,4 +1,8 @@
from django.db import models
+from django.core.exceptions import ValidationError
+
+import socket
+from urlparse import urlparse
TIER_CHOICES = (
(0, 'Tier 0'),
@@ -47,13 +51,43 @@ class MirrorProtocol(models.Model):
class Meta:
verbose_name = 'Mirror Protocol'
+ ordering = ('protocol',)
class MirrorUrl(models.Model):
url = models.CharField(max_length=255)
- protocol = models.ForeignKey(MirrorProtocol, related_name="urls")
+ protocol = models.ForeignKey(MirrorProtocol, related_name="urls",
+ editable=False)
mirror = models.ForeignKey(Mirror, related_name="urls")
- has_ipv4 = models.BooleanField("IPv4 capable", default=True)
- has_ipv6 = models.BooleanField("IPv6 capable", default=False)
+ has_ipv4 = models.BooleanField("IPv4 capable", default=True,
+ editable=False)
+ has_ipv6 = models.BooleanField("IPv6 capable", default=False,
+ editable=False)
+
+ def address_families(self):
+ hostname = urlparse(self.url).hostname
+ info = socket.getaddrinfo(hostname, None, 0, socket.SOCK_STREAM)
+ families = [x[0] for x in info]
+ return families
+
+ @property
+ def hostname(self):
+ return urlparse(self.url).hostname
+
+ def clean(self):
+ try:
+ # Auto-map the protocol field by looking at the URL
+ protocol = urlparse(self.url).scheme
+ self.protocol = MirrorProtocol.objects.get(protocol=protocol)
+ except Exception as e:
+ raise ValidationError(e)
+ try:
+ families = self.address_families()
+ self.has_ipv4 = socket.AF_INET in families
+ self.has_ipv6 = socket.AF_INET6 in families
+ except socket.error as e:
+ # We don't fail in this case; we'll just set both to False
+ self.has_ipv4 = False
+ self.has_ipv6 = False
def __unicode__(self):
return self.url
diff --git a/mirrors/urls.py b/mirrors/urls.py
new file mode 100644
index 00000000..fed9c807
--- /dev/null
+++ b/mirrors/urls.py
@@ -0,0 +1,10 @@
+from django.conf.urls.defaults import patterns
+
+urlpatterns = patterns('mirrors.views',
+ (r'^$', 'mirrors', {}, 'mirror-list'),
+ (r'^status/$', 'status', {}, 'mirror-status'),
+ (r'^status/json/$', 'status_json', {}, 'mirror-status-json'),
+ (r'^(?P<name>[\.\-\w]+)/$', 'mirror_details'),
+)
+
+# vim: set ts=4 sw=4 et:
diff --git a/mirrors/urls_mirrorlist.py b/mirrors/urls_mirrorlist.py
new file mode 100644
index 00000000..70bc18d2
--- /dev/null
+++ b/mirrors/urls_mirrorlist.py
@@ -0,0 +1,12 @@
+from django.conf.urls.defaults import patterns
+
+urlpatterns = patterns('mirrors.views',
+ (r'^$', 'generate_mirrorlist', {}, 'mirrorlist'),
+ (r'^all/$', 'find_mirrors', {'countries': ['all']}),
+ (r'^all/ftp/$', 'find_mirrors',
+ {'countries': ['all'], 'protocols': ['ftp']}),
+ (r'^all/http/$', 'find_mirrors',
+ {'countries': ['all'], 'protocols': ['http']}),
+)
+
+# vim: set ts=4 sw=4 et: