Add support for mirror selection and redirection.

This commit is contained in:
Magnus Hagander
2010-01-02 19:36:24 +01:00
parent fcc9e08e95
commit 4b9efc5bdc
68 changed files with 172 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

BIN
media/img/flags/Austria.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

BIN
media/img/flags/Belgium.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
media/img/flags/Brazil.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

BIN
media/img/flags/Canada.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

BIN
media/img/flags/Chile.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

BIN
media/img/flags/China.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

BIN
media/img/flags/Croatia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

BIN
media/img/flags/Denmark.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

BIN
media/img/flags/Estonia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

BIN
media/img/flags/Finland.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

BIN
media/img/flags/France.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

BIN
media/img/flags/Georgia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
media/img/flags/Germany.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

BIN
media/img/flags/Greece.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

BIN
media/img/flags/Hungary.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

BIN
media/img/flags/Iceland.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

BIN
media/img/flags/India.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

BIN
media/img/flags/Ireland.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

BIN
media/img/flags/Israel.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

BIN
media/img/flags/Italy.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

BIN
media/img/flags/Japan.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

BIN
media/img/flags/Korea.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

BIN
media/img/flags/Latvia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

BIN
media/img/flags/Mexico.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

BIN
media/img/flags/Norway.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

BIN
media/img/flags/Poland.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
media/img/flags/Romania.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

BIN
media/img/flags/Russia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

BIN
media/img/flags/Serbia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

BIN
media/img/flags/Spain.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

BIN
media/img/flags/Sweden.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

BIN
media/img/flags/Taiwan.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

BIN
media/img/flags/Turkey.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

BIN
media/img/flags/USA.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

BIN
media/img/flags/Ukraine.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
media/img/flags/Vietnam.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

View File

@ -2,12 +2,19 @@ from django.contrib import admin
from util.admin import register_markdown, MarkdownPreviewAdmin from util.admin import register_markdown, MarkdownPreviewAdmin
from models import * from models import *
class MirrorAdmin(admin.ModelAdmin):
list_display = ('__unicode__', 'country_name', 'country_code', 'mirror_index', 'mirror_last_rsync', 'host_sponsor', )
list_filter = ('country_name', 'mirror_active', )
search_fields = ('country_name', 'host_sponsor', 'host_notes', )
ordering = ('country_code', )
class ProductAdmin(MarkdownPreviewAdmin): class ProductAdmin(MarkdownPreviewAdmin):
list_display = ('name', 'publisher', 'approved', 'lastconfirmed',) list_display = ('name', 'publisher', 'approved', 'lastconfirmed',)
list_filter = ('approved',) list_filter = ('approved',)
search_fields = ('name', 'description', ) search_fields = ('name', 'description', )
ordering = ('name', ) ordering = ('name', )
admin.site.register(Mirror, MirrorAdmin)
admin.site.register(Category) admin.site.register(Category)
admin.site.register(LicenceType) admin.site.register(LicenceType)
admin.site.register(Product, ProductAdmin) admin.site.register(Product, ProductAdmin)

View File

@ -6,6 +6,50 @@ from pgweb.core.models import Organisation
from datetime import datetime from datetime import datetime
class Mirror(models.Model):
country_name = models.CharField(max_length=50, null=False, blank=False)
country_code = models.CharField(max_length=2, null=False, blank=False)
mirror_created = models.DateTimeField(null=False, blank=False, default=datetime.now())
mirror_last_rsync = models.DateTimeField(null=False, blank=False, default=datetime(1970,1,1))
mirror_index = models.IntegerField(null=False)
host_addr = models.IPAddressField(null=True, default='0.0.0.0')
host_path = models.CharField(max_length=100, null=True)
host_sponsor = models.CharField(max_length=100, null=True)
host_contact = models.CharField(max_length=100, null=True)
host_email = models.CharField(max_length=100, null=True)
host_notes = models.TextField(null=True)
rsync_host1 = models.CharField(max_length=100, null=True)
rsync_host2 = models.CharField(max_length=100, null=True)
mirror_active = models.BooleanField(null=False, default=True)
mirror_dns = models.BooleanField(null=False, default=False)
mirror_private = models.BooleanField(null=False, default=False)
host_use_cname = models.BooleanField(null=True, default=False)
host_cname_host = models.CharField(max_length=100, null=True)
mirror_primary = models.BooleanField(null=False, default=False)
error_count = models.IntegerField(null=False, default=0)
alternate_protocol = models.BooleanField(null=False, default=False)
alternate_at_root = models.BooleanField(null=False, default=False)
class Meta:
db_table='mirrors'
def __unicode__(self):
return "%s.%s" % (self.country_code, self.mirror_index)
def get_host_name(self):
if self.mirror_index == 0:
return "ftp.%s.postgresql.org" % self.country_code
else:
return "ftp%s.%s.postgresql.org" % (self.mirror_index, self.country_code)
def get_root_path(self, method):
if method == 'f' or not self.alternate_at_root:
# FTP method, or http with same path, build complete one
return ("%s/%s" % (self.get_host_name(), self.host_path)).replace('//','/').rstrip('/')
else:
# http with alternate_at_root - thus, ignore the path element
return self.get_host_name()
class Category(models.Model): class Category(models.Model):
catname = models.CharField(max_length=100, null=False, blank=False) catname = models.CharField(max_length=100, null=False, blank=False)
blurb = models.TextField(null=False, blank=True) blurb = models.TextField(null=False, blank=True)

View File

@ -2,10 +2,12 @@ from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse, Http404, HttpResponseRedirect from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import TemplateDoesNotExist, loader, Context from django.template import TemplateDoesNotExist, loader, Context
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db import connection, transaction
from django.conf import settings from django.conf import settings
import os import os
from datetime import datetime from datetime import datetime
import urlparse
from pgweb.util.decorators import ssl_required from pgweb.util.decorators import ssl_required
from pgweb.util.contexts import NavContext from pgweb.util.contexts import NavContext
@ -103,7 +105,76 @@ def ftpbrowser(request, subpath):
'maintainer': _getfile(fspath, 'CURRENT_MAINTAINER'), 'maintainer': _getfile(fspath, 'CURRENT_MAINTAINER'),
}, NavContext(request, 'download')) }, NavContext(request, 'download'))
def _get_numeric_ip(request):
try:
ip = request.META['REMOTE_ADDR']
p = ip.split('.')
return int(p[0])*16777216 + int(p[1])*65536 + int(p[2])*256 + int(p[3])
except:
return None
def mirrorselect(request, path):
try:
numericip = _get_numeric_ip(request)
near_mirrors = Mirror.objects.filter(mirror_active=True, mirror_private=False, mirror_dns=True).extra(where=["mirror_last_rsync>(now() - '48 hours'::interval)","country_code IN (SELECT lower(countrycode) FROM iptocountry WHERE %s BETWEEN startip AND endip)" % numericip]).order_by('country_name', 'mirror_index')
except:
near_mirrors = None
all_mirrors = Mirror.objects.filter(mirror_active=True, mirror_private=False, mirror_dns=True).extra(where=["mirror_last_rsync>(now() - '48 hours'::interval)"]).order_by('country_name', 'mirror_index')
return render_to_response('downloads/mirrorselect.html', {
'path': path,
'all_mirrors': all_mirrors,
'near_mirrors': near_mirrors,
'masterserver': settings.MASTERSITE_ROOT,
}, NavContext(request, 'download'))
def _mirror_redirect_internal(request, scheme, host, path):
# Log the access
curs = connection.cursor()
curs.execute("""INSERT INTO clickthrus (scheme, host, path, country)
VALUES (%(scheme)s, %(host)s, %(path)s, (
SELECT countrycode FROM iptocountry WHERE %(ip)s BETWEEN startip and endip LIMIT 1))""", {
'scheme': scheme,
'host': host,
'path': path,
'ip': _get_numeric_ip(request),
})
transaction.commit_unless_managed()
# Redirect!
newurl = "%s://%s/%s" % (scheme, host, path)
return HttpResponseRedirect(newurl)
def mirror_redirect(request, mirrorid, protocol, path):
try:
mirror = Mirror.objects.get(pk=mirrorid)
except Mirror.NotFound:
raise Http404("Specified mirror not found")
return _mirror_redirect_internal(
request,
protocol=='h' and 'http' or 'ftp',
mirror.get_root_path(protocol),
path,
)
def mirror_redirect_old(request):
# Version of redirect that takes parameters in the querystring. This is
# only used by the stackbuilder.
if not request.GET['sb'] == "1":
raise Http404("Page not found, you should be using the new URL format!")
urlpieces = urlparse.urlparse(request.GET['url'])
if urlpieces.query:
path = "%s?%s" % (urlpieces.path, urlpieces.query)
else:
path = urlpieces.path
return _mirror_redirect_internal(
request,
urlpieces.scheme,
urlpieces.netloc,
path,
)
####### #######
# Product catalogue # Product catalogue

View File

@ -107,6 +107,7 @@ INSTALLED_APPS = [
SITE_ROOT="http://www.postgresql.org" SITE_ROOT="http://www.postgresql.org"
MASTERSITE_ROOT="http://wwwmaster.postgresql.org"
# Load local settings overrides # Load local settings overrides
from settings_local import * from settings_local import *

View File

@ -29,8 +29,11 @@ urlpatterns = patterns('',
(r'^about/quotesarchive/$', 'quotes.views.allquotes'), (r'^about/quotesarchive/$', 'quotes.views.allquotes'),
(r'^ftp/(.*/)?$', 'downloads.views.ftpbrowser'), (r'^ftp/(.*/)?$', 'downloads.views.ftpbrowser'),
(r'^download/mirrors-ftp/+(.*)$', 'downloads.views.mirrorselect'),
(r'^download/product-categories/$', 'downloads.views.categorylist'), (r'^download/product-categories/$', 'downloads.views.categorylist'),
(r'^download/products/(\d+)(-.*)?/$', 'downloads.views.productlist'), (r'^download/products/(\d+)(-.*)?/$', 'downloads.views.productlist'),
(r'^redir/(\d+)/([hf])/([a-zA-Z0-9/\._-]+)$', 'downloads.views.mirror_redirect'),
(r'^redir$', 'downloads.views.mirror_redirect_old'),
(r'^docs/(current|\d\.\d)/(static|interactive)/(.*).html$', 'docs.views.docpage'), (r'^docs/(current|\d\.\d)/(static|interactive)/(.*).html$', 'docs.views.docpage'),

View File

@ -0,0 +1,9 @@
<div class="mirrorselect">
<img src="/media/img/flags/{{mirror.country_name|cut:" "}}.gif" alt="{{mirror.country_name}}" title="{{mirror.country_name}}" width="32" height="21" style="border: 1px" />
<br/>
{%if mirror.alternate_protocol %}
<a href="{{masterserver}}/redir/{{mirror.id}}/h/{{path}}">http</a> |
{%endif%}
<a href="{{masterserver}}/redir/{{mirror.id}}/f/{{path}}">ftp</a>
</div>

View File

@ -0,0 +1,37 @@
{%extends "base/page.html"%}
{%block title%}Choose a download mirror{%endblock%}
{%block extrahead%}
<style>
div.mirrorselect {
// border: 1px solid black;
display: inline-block;
width: 110px;
text-align: center;
height: 50px;
}
</style>
{%endblock%}
{%block contents%}
<h1>Choose a download mirror</h1>
<p><b>Downloading: </b> {{path}}</p>
{%if near_mirrors%}
<p><b>We think these mirrors are near you:</b></p>
<div id="nearmirrorwrap">
{%for mirror in near_mirrors%}
{%include "downloads/inc_mirror.html"%}
{%endfor%}
</div>
{%endif%}
<p><b>Choose any other mirror in the world:</b></p>
<div id="mainmirrorwrap">
{%for mirror in all_mirrors%}
{%include "downloads/inc_mirror.html"%}
{%endfor%}
</div>
<p><a href="/mirror/howto">Read this</a> if you would like to host a mirror.</p>
{%endblock%}