Login

Making multi node / multi vhost easier!

Author:
sleepycal
Posted:
March 7, 2011
Language:
Python
Version:
1.2
Score:
0 (after 1 ratings)

Some simple scripts which allow you to do nicer multi node / multi hostname hosting from within Django.

Cal Leeming Simplicity Media Ltd

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""
Cal Leeming [Simplicity Media Ltd] - March 2011
cal.leeming [at] simplicitymedialtd.co.uk

"""

#####################################################
# multihost.py
#####################################################

from django.conf import settings
from django.utils.cache import patch_vary_headers

import socket

class MultiHostMiddleware:

    def process_request(self, request):
        try:
            host = request.META["HTTP_HOST"]
            if host[-3:] == ":80":
                host = host[:-3] # ignore default port number, if present
            request.urlconf = settings.HOST_MIDDLEWARE_URLCONF_MAP[host]
            
            if settings.HOST_MIDDLEWARE_URLCONF_MAP_RESTRICT.has_key(host):
                if not socket.gethostname() in settings.HOST_MIDDLEWARE_URLCONF_MAP_RESTRICT[host]:
                    raise Exception, "The requested site is not authorized to be served from this node."
                
        except KeyError:
            pass # use default urlconf (settings.ROOT_URLCONF)

    def process_response(self, request, response):
        if getattr(request, "urlconf", None):
            patch_vary_headers(response, ('Host',))
        return response


#####################################################
# settings.py
#####################################################


if not os.environ.has_key('DJANGO_ENVIRONMENT'):
    raise Exception, "You must provide environ DJANGO_ENVIRONMENT (dev/prod)"

# Place environment specific overrides in here
if os.environ['DJANGO_ENVIRONMENT']=='dev':
    DEBUG = True

elif os.environ['DJANGO_ENVIRONMENT']=='prod':
    DEBUG = False

DATABASES = {
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db1',
        'USER': 'db1',
        'PASSWORD': 'db1',
        'HOST': 'db1'
    },
    
    'db2': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db2',
        'USER': 'db2',
        'PASSWORD': 'db2',
        'HOST': 'db2'
    },
}


"""Monkey Patch to allow imports from the webapp dir, and also
not have to specify an absolute template location. This lets you specify
relative paths to the webapp across multiple nodes."""
import os
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__)+"/").replace('\\',"/")
TEMPLATE_DIRS = (PROJECT_PATH+'/templates/')

"""
Determine which default database we should use.
Because this webapp runs on multiple servers in different context,
we need to override this here
"""
if socket.gethostname() == 'sws01.internal':
    DATABASES['default'] = DATABASES.get('db1')

    # Cache settings
    CACHE_BACKEND = 'memcached://cache01.internal:11211/'
    TMP_DIR = os.path.realpath(PROJECT_PATH+'/../../tmp')
    
elif socket.gethostname() == 'node02.internal':
    DATABASES['default'] = DATABASES.get('db2')
    TMP_DIR = os.path.realpath(PROJECT_PATH+'/../tmp')

else:
    raise Exception, "Unable to determine which node we are"


"""
Now make sure those paths are OK
"""
if not os.path.isdir(TMP_DIR):
    raise Exception, "Configured settings.TMP_DIR path does not exist."



HOST_MIDDLEWARE_URLCONF_MAP = {
    # Control Panel
    "cp.website1.com": "webapp.sites.website1.urls",

    # Status page
    "cp.website2.com" : "webapp.sites.status2.urls",

    # Members area
    "cp.website3.com" : "webapp.sites.status3.urls",
}

# Restrict certain hostnames to only be served from specific nodes
HOST_MIDDLEWARE_URLCONF_MAP_RESTRICT = {
    # Status page
    "resource.heavy.page.com" : ("sws01.internal", ),
}

MIDDLEWARE_CLASSES = (
    'webapp.multihost.MultiHostMiddleware',
)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

Please login first before commenting.