From 116751e4bab183b3cca93ab13f7f4f21c752be4e Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 24 Apr 2012 23:22:23 -0500 Subject: Rename mirror country fields to country_old in prep for normalization We're going to move to using ISO 2 character codes via django countries, so start by moving the old data out of the way first. Signed-off-by: Dan McGee --- mirrors/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'mirrors/views.py') diff --git a/mirrors/views.py b/mirrors/views.py index e93097a3..c5989d67 100644 --- a/mirrors/views.py +++ b/mirrors/views.py @@ -23,7 +23,7 @@ class MirrorlistForm(forms.Form): def __init__(self, *args, **kwargs): super(MirrorlistForm, self).__init__(*args, **kwargs) countries = Mirror.objects.filter(active=True).values_list( - 'country', flat=True).distinct().order_by('country') + 'country_old', flat=True).distinct().order_by('country_old') self.fields['country'].choices = [('all','All')] + make_choice( countries) self.fields['country'].initial = ['all'] @@ -62,8 +62,8 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False, mirror__public=True, mirror__active=True, ) if countries and 'all' not in countries: - qset = qset.filter(Q(country__in=countries) | - Q(mirror__country__in=countries)) + qset = qset.filter(Q(country_old__in=countries) | + Q(mirror__country_old__in=countries)) ip_version = Q() if ipv4_supported: @@ -97,7 +97,7 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False, mimetype='text/plain') def mirrors(request): - mirror_list = Mirror.objects.select_related().order_by('tier', 'country') + mirror_list = Mirror.objects.select_related().order_by('tier', 'country_old') if not request.user.is_authenticated(): mirror_list = mirror_list.filter(public=True, active=True) return direct_to_template(request, 'mirrors/mirrors.html', -- cgit v1.2.3-54-g00ecf From 640e0f58645a7fd07f3c6185d9583b4d218e2468 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 25 Apr 2012 01:32:57 -0500 Subject: Finish django countries implementation * Add a migration to drop the old countries field. * Update all templates/views/utility methods to point at the new country field and dereference it as necessary. * Add the flags images to a few views where it makes sense. * Cleanup the download page layout quite a bit. * Bump the mirror status JSON version to 3; add country_code attribute. Signed-off-by: Dan McGee --- ...country_old__del_field_mirrorurl_country_old.py | 76 ++++++++++++++++++++++ mirrors/models.py | 9 +-- mirrors/utils.py | 17 ++--- mirrors/views.py | 62 ++++++++++++------ public/views.py | 18 +++-- sitestatic/archweb.css | 19 ------ templates/mirrors/mirror_details.html | 2 +- templates/mirrors/mirrorlist.txt | 2 +- templates/mirrors/mirrorlist_status.txt | 3 +- templates/mirrors/mirrors.html | 16 ++--- templates/mirrors/status.html | 2 +- templates/mirrors/status_table.html | 2 +- templates/public/download.html | 43 +++++------- 13 files changed, 168 insertions(+), 103 deletions(-) create mode 100644 mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py (limited to 'mirrors/views.py') diff --git a/mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py b/mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py new file mode 100644 index 00000000..ae917ec0 --- /dev/null +++ b/mirrors/migrations/0016_auto__del_field_mirror_country_old__del_field_mirrorurl_country_old.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.delete_column('mirrors_mirror', 'country_old') + db.delete_column('mirrors_mirrorurl', 'country_old') + db.create_index('mirrors_mirror', ['country']) + db.create_index('mirrors_mirrorurl', ['country']) + + def backwards(self, orm): + db.delete_index('mirrors_mirrorurl', ['country']) + db.delete_index('mirrors_mirror', ['country']) + db.add_column('mirrors_mirror', 'country_old', + self.gf('django.db.models.fields.CharField')(default='Any', max_length=255, db_index=True), + keep_default=False) + db.add_column('mirrors_mirrorurl', 'country_old', + self.gf('mirrors.models.NullCharField')(blank=True, max_length=255, null=True, db_index=True), + keep_default=False) + + models = { + 'mirrors.mirror': { + 'Meta': {'ordering': "('country', 'name')", 'object_name': 'Mirror'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django_countries.fields.CountryField', [], {'db_index': 'True', 'max_length': '2', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'rsync_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}), + 'rsync_user': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}), + 'tier': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}), + 'upstream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['mirrors.Mirror']", 'null': 'True', 'on_delete': 'models.SET_NULL'}) + }, + 'mirrors.mirrorlog': { + 'Meta': {'object_name': 'MirrorLog'}, + 'check_time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'error': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_success': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'logs'", 'to': "orm['mirrors.MirrorUrl']"}) + }, + 'mirrors.mirrorprotocol': { + 'Meta': {'ordering': "('protocol',)", 'object_name': 'MirrorProtocol'}, + 'default': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_download': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'}) + }, + 'mirrors.mirrorrsync': { + 'Meta': {'object_name': 'MirrorRsync'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}), + 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['mirrors.Mirror']"}) + }, + 'mirrors.mirrorurl': { + 'Meta': {'object_name': 'MirrorUrl'}, + 'country': ('django_countries.fields.CountryField', [], {'db_index': 'True', 'max_length': '2', 'blank': 'True'}), + 'has_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'has_ipv6': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['mirrors.Mirror']"}), + 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'on_delete': 'models.PROTECT', 'to': "orm['mirrors.MirrorProtocol']"}), + 'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + } + } + + complete_apps = ['mirrors'] diff --git a/mirrors/models.py b/mirrors/models.py index 79968412..c23622fa 100644 --- a/mirrors/models.py +++ b/mirrors/models.py @@ -25,8 +25,7 @@ class Mirror(models.Model): name = models.CharField(max_length=255, unique=True) tier = models.SmallIntegerField(default=2, choices=TIER_CHOICES) upstream = models.ForeignKey('self', null=True, on_delete=models.SET_NULL) - country_old = models.CharField(max_length=255, db_index=True) - country = CountryField(blank=True) + country = CountryField(blank=True, db_index=True) admin_email = models.EmailField(max_length=255, blank=True) public = models.BooleanField(default=True) active = models.BooleanField(default=True) @@ -70,9 +69,7 @@ class MirrorUrl(models.Model): protocol = models.ForeignKey(MirrorProtocol, related_name="urls", editable=False, on_delete=models.PROTECT) mirror = models.ForeignKey(Mirror, related_name="urls") - country_old = NullCharField(max_length=255, null=True, blank=True, - db_index=True) - country = CountryField(blank=True) + country = CountryField(blank=True, db_index=True) has_ipv4 = models.BooleanField("IPv4 capable", default=True, editable=False) has_ipv6 = models.BooleanField("IPv6 capable", default=False, @@ -90,7 +87,7 @@ def hostname(self): @property def real_country(self): - return self.country_old or self.mirror.country_old + return self.country or self.mirror.country def clean(self): try: diff --git a/mirrors/utils.py b/mirrors/utils.py index aa1e9f76..728c3040 100644 --- a/mirrors/utils.py +++ b/mirrors/utils.py @@ -1,6 +1,7 @@ from datetime import timedelta from django.db.models import Avg, Count, Max, Min, StdDev +from django_countries.fields import Country from main.utils import cache_function, utc_now from .models import MirrorLog, MirrorProtocol, MirrorUrl @@ -89,13 +90,14 @@ def get_mirror_errors(cutoff=default_cutoff): errors = MirrorLog.objects.filter( is_success=False, check_time__gte=cutoff_time, url__mirror__active=True, url__mirror__public=True).values( - 'url__url', 'url__country_old', 'url__protocol__protocol', - 'url__mirror__country_old', 'error').annotate( + 'url__url', 'url__country', 'url__protocol__protocol', + 'url__mirror__country', 'error').annotate( error_count=Count('error'), last_occurred=Max('check_time') ).order_by('-last_occurred', '-error_count') errors = list(errors) for err in errors: - err['country'] = err['url__country_old'] or err['url__mirror__country_old'] + ctry_code = err['url__country'] or err['url__mirror__country'] + err['country'] = Country(ctry_code) return errors @@ -114,16 +116,15 @@ def get_mirror_url_for_download(cutoff=default_cutoff): best_logs = MirrorLog.objects.filter(is_success=True, check_time__gte=min_check_time, last_sync__gte=min_sync_time, url__mirror__public=True, url__mirror__active=True, - url__protocol__protocol__iexact='HTTP').order_by( + url__protocol__default=True).order_by( 'duration')[:1] if best_logs: return MirrorUrl.objects.get(id=best_logs[0].url_id) mirror_urls = MirrorUrl.objects.filter( - mirror__public=True, mirror__active=True, - protocol__protocol__iexact='HTTP') - # look first for an 'Any' URL, then fall back to any HTTP URL - filtered_urls = mirror_urls.filter(mirror__country_old='Any')[:1] + mirror__public=True, mirror__active=True, protocol__default=True) + # look first for a country-agnostic URL, then fall back to any HTTP URL + filtered_urls = mirror_urls.filter(mirror__country='')[:1] if not filtered_urls: filtered_urls = mirror_urls[:1] if not filtered_urls: diff --git a/mirrors/views.py b/mirrors/views.py index c5989d67..349c17d1 100644 --- a/mirrors/views.py +++ b/mirrors/views.py @@ -1,3 +1,6 @@ +import datetime +from operator import attrgetter, itemgetter + from django import forms from django.core.serializers.json import DjangoJSONEncoder from django.db.models import Q @@ -6,12 +9,13 @@ from django.views.decorators.csrf import csrf_exempt from django.views.generic.simple import direct_to_template from django.utils import simplejson +from django_countries.countries import COUNTRIES -from main.utils import make_choice from .models import Mirror, MirrorUrl, MirrorProtocol from .utils import get_mirror_statuses, get_mirror_errors -import datetime +COUNTRY_LOOKUP = dict(COUNTRIES) + class MirrorlistForm(forms.Form): country = forms.MultipleChoiceField(required=False) @@ -22,17 +26,27 @@ class MirrorlistForm(forms.Form): def __init__(self, *args, **kwargs): super(MirrorlistForm, self).__init__(*args, **kwargs) - countries = Mirror.objects.filter(active=True).values_list( - 'country_old', flat=True).distinct().order_by('country_old') - self.fields['country'].choices = [('all','All')] + make_choice( - countries) - self.fields['country'].initial = ['all'] - protos = make_choice( - MirrorProtocol.objects.filter(is_download=True)) + fields = self.fields + fields['country'].choices = [('all','All')] + self.get_countries() + fields['country'].initial = ['all'] + protos = [(p.protocol, p.protocol) for p in + MirrorProtocol.objects.filter(is_download=True)] initial = MirrorProtocol.objects.filter(is_download=True, default=True) - self.fields['protocol'].choices = protos - self.fields['protocol'].initial = [p.protocol for p in initial] - self.fields['ip_version'].initial = ['4'] + fields['protocol'].choices = protos + fields['protocol'].initial = [p.protocol for p in initial] + fields['ip_version'].initial = ['4'] + + def get_countries(self): + country_codes = set() + country_codes.update(Mirror.objects.filter(active=True).exclude( + country='').values_list( + 'country', flat=True).order_by().distinct()) + country_codes.update(MirrorUrl.objects.filter( + mirror__active=True).exclude(country='').values_list( + 'country', flat=True).order_by().distinct()) + countries = [(code, COUNTRY_LOOKUP[code]) for code in country_codes] + return sorted(countries, key=itemgetter(1)) + @csrf_exempt def generate_mirrorlist(request): @@ -52,6 +66,7 @@ def generate_mirrorlist(request): return direct_to_template(request, 'mirrors/index.html', {'mirrorlist_form': form}) + def find_mirrors(request, countries=None, protocols=None, use_status=False, ipv4_supported=True, ipv6_supported=True): if not protocols: @@ -62,8 +77,8 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False, mirror__public=True, mirror__active=True, ) if countries and 'all' not in countries: - qset = qset.filter(Q(country_old__in=countries) | - Q(mirror__country_old__in=countries)) + qset = qset.filter(Q(country__in=countries) | + Q(mirror__country__in=countries)) ip_version = Q() if ipv4_supported: @@ -74,7 +89,7 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False, if not use_status: urls = qset.order_by('mirror__name', 'url') - urls = sorted(urls, key=lambda x: x.real_country) + urls = sorted(urls, key=attrgetter('real_country')) template = 'mirrors/mirrorlist.txt' else: status_info = get_mirror_statuses() @@ -96,13 +111,15 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False, }, mimetype='text/plain') + def mirrors(request): - mirror_list = Mirror.objects.select_related().order_by('tier', 'country_old') + mirror_list = Mirror.objects.select_related().order_by('tier', 'country') if not request.user.is_authenticated(): mirror_list = mirror_list.filter(public=True, active=True) return direct_to_template(request, 'mirrors/mirrors.html', {'mirror_list': mirror_list}) + def mirror_details(request, name): mirror = get_object_or_404(Mirror, name=name) if not request.user.is_authenticated() and \ @@ -116,11 +133,12 @@ def mirror_details(request, name): # get each item from checked_urls and supplement with anything in all_urls # if it wasn't there all_urls = set(checked_urls).union(all_urls) - all_urls = sorted(all_urls, key=lambda x: x.url) + all_urls = sorted(all_urls, key=attrgetter('url')) return direct_to_template(request, 'mirrors/mirror_details.html', {'mirror': mirror, 'urls': all_urls}) + def status(request): bad_timedelta = datetime.timedelta(days=3) status_info = get_mirror_statuses() @@ -143,6 +161,7 @@ def status(request): }) return direct_to_template(request, 'mirrors/status.html', context) + class MirrorStatusJSONEncoder(DjangoJSONEncoder): '''Base JSONEncoder extended to handle datetime.timedelta and MirrorUrl serialization. The base class takes care of datetime.datetime types.''' @@ -159,17 +178,20 @@ def default(self, obj): if isinstance(obj, MirrorUrl): data = dict((attr, getattr(obj, attr)) for attr in self.url_attributes) - # separate because it isn't on the URL directly - data['country'] = obj.real_country + # get any override on the country attribute first + country = obj.real_country + data['country'] = unicode(country.name) + data['country_code'] = country.code return data if isinstance(obj, MirrorProtocol): return unicode(obj) return super(MirrorStatusJSONEncoder, self).default(obj) + def status_json(request): status_info = get_mirror_statuses() data = status_info.copy() - data['version'] = 2 + data['version'] = 3 to_json = simplejson.dumps(data, ensure_ascii=False, cls=MirrorStatusJSONEncoder) response = HttpResponse(to_json, mimetype='application/json') diff --git a/public/views.py b/public/views.py index e149d921..3ea8f841 100644 --- a/public/views.py +++ b/public/views.py @@ -1,11 +1,11 @@ from datetime import datetime +from operator import attrgetter from django.conf import settings from django.contrib.auth.models import User from django.db.models import Count, Q from django.http import Http404 from django.views.decorators.cache import cache_control -from django.views.generic import list_detail from django.views.generic.simple import direct_to_template from devel.models import MasterKey, PGPSignature @@ -66,19 +66,17 @@ def donate(request): @cache_control(max_age=300) def download(request): - qset = MirrorUrl.objects.select_related('mirror', 'protocol').filter( - protocol__is_download=True, - mirror__public=True, mirror__active=True, mirror__isos=True - ) + mirror_urls = MirrorUrl.objects.select_related('mirror').filter( + protocol__default=True, + mirror__public=True, mirror__active=True, mirror__isos=True) + sort_by = attrgetter('real_country.name', 'mirror.name') + mirror_urls = sorted(mirror_urls, key=sort_by) context = { 'releng_iso_url': settings.ISO_LIST_URL, 'releng_pxeboot_url': settings.PXEBOOT_URL, + 'mirror_urls': mirror_urls, } - return list_detail.object_list(request, - qset.order_by('mirror__country_old', 'mirror__name', 'protocol'), - template_name="public/download.html", - template_object_name="mirror_url", - extra_context=context) + return direct_to_template(request, 'public/download.html', context) @cache_control(max_age=300) def feeds(request): diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css index a7fe6cac..1df05071 100644 --- a/sitestatic/archweb.css +++ b/sitestatic/archweb.css @@ -588,25 +588,6 @@ table#download-torrents .cpu-arch { text-align: center; } -table#download-mirrors { - width: auto; - margin-bottom: 1em; -} - - table#download-mirrors td.mirror-country { - padding-top: 1em; - } - - table#download-mirrors td.mirror-server { - padding-right: 1em; - } - - table#download-mirrors a { - display: block; - float: right; - width: 4em; - } - /* pkglists/devlists */ table.results { font-size: 0.846em; diff --git a/templates/mirrors/mirror_details.html b/templates/mirrors/mirror_details.html index bb3b417c..6fe68f36 100644 --- a/templates/mirrors/mirror_details.html +++ b/templates/mirrors/mirror_details.html @@ -21,7 +21,7 @@

Mirror Details: {{ mirror.name }}

Country: - {{ mirror.country_old }} + {{ mirror.country.name|default:'Worldwide' }} Has ISOs: diff --git a/templates/mirrors/mirrorlist.txt b/templates/mirrors/mirrorlist.txt index 24b52fa1..d3dd6e4e 100644 --- a/templates/mirrors/mirrorlist.txt +++ b/templates/mirrors/mirrorlist.txt @@ -8,6 +8,6 @@ content right, and then go back later to fix it all up. ## Generated on {% now "Y-m-d" %} ##{% for mirror_url in mirror_urls %}{% ifchanged %} -## {{ mirror_url.real_country }}{% endifchanged %} +## {{ mirror_url.real_country.name|default:'Worldwide' }}{% endifchanged %} #Server = {{ mirror_url.url}}$repo/os/$arch{% endfor %} {% endautoescape %} diff --git a/templates/mirrors/mirrorlist_status.txt b/templates/mirrors/mirrorlist_status.txt index e3504395..523794b2 100644 --- a/templates/mirrors/mirrorlist_status.txt +++ b/templates/mirrors/mirrorlist_status.txt @@ -7,7 +7,8 @@ content right, and then go back later to fix it all up. ## Arch Linux repository mirrorlist ## Sorted by mirror score from mirror status page ## Generated on {% now "Y-m-d" %} +## {% for mirror_url in mirror_urls %} -## Score: {{ mirror_url.score|floatformat:1|default:'unknown' }}, {{ mirror_url.real_country }} +## Score: {{ mirror_url.score|floatformat:1|default:'unknown' }}, {{ mirror_url.real_country.name|default:'Worldwide' }} #Server = {{ mirror_url.url}}$repo/os/$arch{% endfor %} {% endautoescape %} diff --git a/templates/mirrors/mirrors.html b/templates/mirrors/mirrors.html index 4b59058a..19c6ea27 100644 --- a/templates/mirrors/mirrors.html +++ b/templates/mirrors/mirrors.html @@ -26,15 +26,15 @@

Mirror Overview

{{ mirror.name }} - {{mirror.get_tier_display}} - {{mirror.country_old}} - {{mirror.isos|yesno|capfirst}} - {{mirror.supported_protocols|join:", "}} + {{ mirror.get_tier_display }} + {% if mirror.country %} {% endif %}{{ mirror.country.name }} + {{ mirror.isos|yesno|capfirst }} + {{ mirror.supported_protocols|join:", " }} {% if user.is_authenticated %} - {{mirror.public|yesno|capfirst}} - {{mirror.active|yesno|capfirst}} - {{mirror.admin_email}} - {{mirror.notes|linebreaks}} + {{ mirror.public|yesno|capfirst }} + {{ mirror.active|yesno|capfirst }} + {{ mirror.admin_email }} + {{ mirror.notes|linebreaks }} {% endif %} {% endfor %} diff --git a/templates/mirrors/status.html b/templates/mirrors/status.html index 225572ee..8f814448 100644 --- a/templates/mirrors/status.html +++ b/templates/mirrors/status.html @@ -92,7 +92,7 @@

Mirror Syncing Error Log

{% spaceless %} {{ log.url__url }} {{ log.url__protocol__protocol }} - {{ log.country }} + {% if log.country %} {% endif %}{{ log.country.name }} {{ log.error }} {{ log.last_occurred|date:'Y-m-d H:i' }} {{ log.error_count }} diff --git a/templates/mirrors/status_table.html b/templates/mirrors/status_table.html index bd70115c..3a20c068 100644 --- a/templates/mirrors/status_table.html +++ b/templates/mirrors/status_table.html @@ -18,7 +18,7 @@ {% spaceless %} {{ m_url.url }} {{ m_url.protocol }} - {{ m_url.real_country }} + {% if m_url.real_country %} {% endif %}{{ m_url.real_country.name }} {{ m_url.last_sync|date:'Y-m-d H:i'|default:'unknown' }} {{ m_url.completion_pct|percentage:1 }} {{ m_url.delay|duration|default:'unknown' }} diff --git a/templates/public/download.html b/templates/public/download.html index fbadb7c0..4d75268a 100644 --- a/templates/public/download.html +++ b/templates/public/download.html @@ -77,7 +77,7 @@

BitTorrent Download (recommended)

Download - Downloads and installs packages versions via FTP for absolute freshness. + Downloads and installs packages versions via mirrors for absolute freshness. @@ -131,10 +131,10 @@

Test ISO Info

title="Release Engineering ISO feedback">Feedback -

HTTP/FTP Direct Downloads

+

HTTP Direct Downloads

In addition to the BitTorrent links above, install images can also be - downloaded via HTTP or FTP from the mirror sites listed below. Please + downloaded via HTTP from the mirror sites listed below. Please ensure the download image matches the checksum from the md5sums.txt or sha1sums.txt file in the same directory as the image.

@@ -150,30 +150,19 @@

Checksums

{% cache 600 download-mirrors %} - - - - - - - - - - - - -

Server Location

Download

- {% for mirror_url in mirror_url_list %} - {% ifchanged mirror_url.mirror.country_old %} -
{{mirror_url.mirror.country_old}} - {% endifchanged %} - {% ifchanged mirror_url.mirror.name %} -
{{mirror_url.mirror.name}} - {% endifchanged %} - {{mirror_url.protocol.protocol|upper}} - {% endfor %} -
+
+ {% regroup mirror_urls by real_country as grouped_urls %} + {% for country in grouped_urls %} + {% if country.grouper %}
{{ country.grouper.name }}
+ {% else %}
Worldwide
{% endif %} + + {% endfor %} +
{% endcache %} {% endwith %} -- cgit v1.2.3-54-g00ecf From 952eba9625c5222e1eee77f711ecb3996998bafb Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 25 Apr 2012 02:20:45 -0500 Subject: Clean up mirrorlist generation form a bit Rename template since it really isn't an index of mirrors at all, and convert the form to use multiple checkboxes for both ftp/http and ipv4/ipv6 selection. Signed-off-by: Dan McGee --- mirrors/views.py | 18 ++++++++++-- sitestatic/archweb.css | 10 +++++++ templates/mirrors/index.html | 44 ------------------------------ templates/mirrors/mirrorlist_generate.html | 44 ++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 47 deletions(-) delete mode 100644 templates/mirrors/index.html create mode 100644 templates/mirrors/mirrorlist_generate.html (limited to 'mirrors/views.py') diff --git a/mirrors/views.py b/mirrors/views.py index 349c17d1..6c08f712 100644 --- a/mirrors/views.py +++ b/mirrors/views.py @@ -2,6 +2,7 @@ from operator import attrgetter, itemgetter from django import forms +from django.forms.widgets import CheckboxSelectMultiple from django.core.serializers.json import DjangoJSONEncoder from django.db.models import Q from django.http import Http404, HttpResponse @@ -19,9 +20,11 @@ class MirrorlistForm(forms.Form): country = forms.MultipleChoiceField(required=False) - protocol = forms.MultipleChoiceField(required=False) + protocol = forms.MultipleChoiceField(required=False, + widget=CheckboxSelectMultiple) ip_version = forms.MultipleChoiceField(required=False, - label="IP version", choices=(('4','IPv4'), ('6','IPv6'))) + label="IP version", choices=(('4','IPv4'), ('6','IPv6')), + widget=CheckboxSelectMultiple) use_mirror_status = forms.BooleanField(required=False) def __init__(self, *args, **kwargs): @@ -47,6 +50,15 @@ def get_countries(self): countries = [(code, COUNTRY_LOOKUP[code]) for code in country_codes] return sorted(countries, key=itemgetter(1)) + def as_div(self): + "Returns this form rendered as HTML s." + return self._html_output( + normal_row = u'%(label)s %(field)s%(help_text)s', + error_row = u'%s', + row_ender = '', + help_text_html = u' %s', + errors_on_separate_row = True) + @csrf_exempt def generate_mirrorlist(request): @@ -63,7 +75,7 @@ def generate_mirrorlist(request): else: form = MirrorlistForm() - return direct_to_template(request, 'mirrors/index.html', + return direct_to_template(request, 'mirrors/mirrorlist_generate.html', {'mirrorlist_form': form}) diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css index fdc356ff..407156f8 100644 --- a/sitestatic/archweb.css +++ b/sitestatic/archweb.css @@ -802,6 +802,16 @@ table td.country { white-space: normal; } +form#list-generator div ul { + list-style: none; + display: inline; + padding-left: 0; +} + + form#list-generator div ul li { + display: inline; + } + /* dev/TU biographies */ div#arch-bio-toc { width: 75%; diff --git a/templates/mirrors/index.html b/templates/mirrors/index.html deleted file mode 100644 index 49907b8f..00000000 --- a/templates/mirrors/index.html +++ /dev/null @@ -1,44 +0,0 @@ -{% extends "base.html" %} -{% load package_extras %} -{% block title %}Arch Linux - Pacman Mirrorlist Generator{% endblock %} - -{% block content %} -
- -

Pacman Mirrorlist Generator

- -

This page generates the most up-to-date mirrorlist possible for Arch - Linux. The data used here comes straight from the developers' internal - mirror database used to track mirror availability and tiering. There are - two main options: get a mirrorlist with every available mirror, or get a - mirrorlist tailored to your geography.

- -

Mirrorlist with all available mirrors

- -

An up-to-date mirrorlist is available containing all currently active - mirrors, optionally filtering by protocol. These URLs requires no GET or - POST parameters so they can be fetched from the command line if desired.

- -

- -

Customized by country mirrorlist

- -

The following form can generate a custom up-to-date - pacman mirrorlist based on geography and - desired protocol(s). Simply replace the contents of - /etc/pacman.d/mirrorlist with your generated list. - Additionally, the mirror status data can be incorporated into the generated - mirror list and used to pre-order the mirrors.

- -
- {{ mirrorlist_form.as_p }} -

-
-
-{% endblock %} - diff --git a/templates/mirrors/mirrorlist_generate.html b/templates/mirrors/mirrorlist_generate.html new file mode 100644 index 00000000..e6f5e28c --- /dev/null +++ b/templates/mirrors/mirrorlist_generate.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} +{% load package_extras %} +{% block title %}Arch Linux - Pacman Mirrorlist Generator{% endblock %} + +{% block content %} +
+ +

Pacman Mirrorlist Generator

+ +

This page generates the most up-to-date mirrorlist possible for Arch + Linux. The data used here comes straight from the developers' internal + mirror database used to track mirror availability and tiering. There are + two main options: get a mirrorlist with every available mirror, or get a + mirrorlist tailored to your geography.

+ +

Mirrorlist with all available mirrors

+ +

An up-to-date mirrorlist is available containing all currently active + mirrors, optionally filtering by protocol. These URLs requires no GET or + POST parameters so they can be fetched from the command line if desired.

+ +

+ +

Customized by country mirrorlist

+ +

The following form can generate a custom up-to-date + pacman mirrorlist based on geography and + desired protocol(s). Simply replace the contents of + /etc/pacman.d/mirrorlist with your generated list. + Additionally, the mirror status data can be incorporated into the generated + mirror list and used to pre-order the mirrors.

+ +
+ {{ mirrorlist_form.as_div }} +

+
+
+{% endblock %} + -- cgit v1.2.3-54-g00ecf From 4dcfaddff526dca2828571326aa7263a3272fcdf Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 25 Apr 2012 07:49:26 -0500 Subject: Ensure sorted order of mirrors in status page matches with JS We had one sorting order in the backend, and another once the JS sorting routine kicked in. Match them so we aren't doing more on the client-side on initial display than we have to. Signed-off-by: Dan McGee --- mirrors/utils.py | 5 ++--- mirrors/views.py | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'mirrors/views.py') diff --git a/mirrors/utils.py b/mirrors/utils.py index 728c3040..32fa3587 100644 --- a/mirrors/utils.py +++ b/mirrors/utils.py @@ -43,8 +43,7 @@ def get_mirror_statuses(cutoff=default_cutoff): last_sync=Max('logs__last_sync'), last_check=Max('logs__check_time'), duration_avg=Avg('logs__duration'), - duration_stddev=StdDev('logs__duration') - ).order_by('-last_sync', '-duration_avg') + duration_stddev=StdDev('logs__duration')) # The Django ORM makes it really hard to get actual average delay in the # above query, so run a seperate query for it and we will process the @@ -112,7 +111,7 @@ def get_mirror_url_for_download(cutoff=default_cutoff): Max('check_time'), Max('last_sync')) if status_data['check_time__max'] is not None: min_check_time = status_data['check_time__max'] - timedelta(minutes=5) - min_sync_time = status_data['last_sync__max'] - timedelta(minutes=30) + min_sync_time = status_data['last_sync__max'] - timedelta(minutes=20) best_logs = MirrorLog.objects.filter(is_success=True, check_time__gte=min_check_time, last_sync__gte=min_sync_time, url__mirror__public=True, url__mirror__active=True, diff --git a/mirrors/views.py b/mirrors/views.py index 6c08f712..c52656f7 100644 --- a/mirrors/views.py +++ b/mirrors/views.py @@ -1,4 +1,4 @@ -import datetime +from datetime import timedelta from operator import attrgetter, itemgetter from django import forms @@ -152,7 +152,7 @@ def mirror_details(request, name): def status(request): - bad_timedelta = datetime.timedelta(days=3) + bad_timedelta = timedelta(days=3) status_info = get_mirror_statuses() urls = status_info['urls'] @@ -167,8 +167,8 @@ def status(request): context = status_info.copy() context.update({ - 'good_urls': good_urls, - 'bad_urls': bad_urls, + 'good_urls': sorted(good_urls, key=attrgetter('score')), + 'bad_urls': sorted(bad_urls, key=lambda u: u.delay or timedelta.max), 'error_logs': get_mirror_errors(), }) return direct_to_template(request, 'mirrors/status.html', context) @@ -181,7 +181,7 @@ class MirrorStatusJSONEncoder(DjangoJSONEncoder): 'delay', 'duration_avg', 'duration_stddev', 'score'] def default(self, obj): - if isinstance(obj, datetime.timedelta): + if isinstance(obj, timedelta): # always returned as integer seconds return obj.days * 24 * 3600 + obj.seconds if hasattr(obj, '__iter__'): -- cgit v1.2.3-54-g00ecf