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 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):
list_display = ('name', 'publisher', 'approved', 'lastconfirmed',)
list_filter = ('approved',)
search_fields = ('name', 'description', )
ordering = ('name', )
admin.site.register(Mirror, MirrorAdmin)
admin.site.register(Category)
admin.site.register(LicenceType)
admin.site.register(Product, ProductAdmin)

View File

@ -6,6 +6,50 @@ from pgweb.core.models import Organisation
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):
catname = models.CharField(max_length=100, null=False, blank=False)
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.template import TemplateDoesNotExist, loader, Context
from django.contrib.auth.decorators import login_required
from django.db import connection, transaction
from django.conf import settings
import os
from datetime import datetime
import urlparse
from pgweb.util.decorators import ssl_required
from pgweb.util.contexts import NavContext
@ -103,7 +105,76 @@ def ftpbrowser(request, subpath):
'maintainer': _getfile(fspath, 'CURRENT_MAINTAINER'),
}, 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

View File

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

View File

@ -29,8 +29,11 @@ urlpatterns = patterns('',
(r'^about/quotesarchive/$', 'quotes.views.allquotes'),
(r'^ftp/(.*/)?$', 'downloads.views.ftpbrowser'),
(r'^download/mirrors-ftp/+(.*)$', 'downloads.views.mirrorselect'),
(r'^download/product-categories/$', 'downloads.views.categorylist'),
(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'),

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%}