Is there anyway to put a django site into maintenance mode using fabric?
Asked Answered
E

3

8

I'm currently using MaintenanceModeMiddleware to put my site into maintenance mode, but it requires you make the change in the settings.py file on the remote server. I would like to use fabric to remotely put the site into maintenance mode. Is there a way to achieve this? Or is there a better method for doing this? Thanks.

[UPDATE]

Thanks for the feedback everyone in the end this is what I did and it works great for me, http://garthhumphreys.com/2011/06/11/painless-django-maintenance-mode-with-fabric/ - I do like the idea of uncomment lines but with my setup if I were to do that on the production server it would be overwritten once I pushed the new version out, so in the end putting the site into maintenance mode from the server level and not the django level works a lot better and is truly easier and flexible, for me at least :)

Ebby answered 10/6, 2011 at 16:34 Comment(2)
this question may be related. I don't know much about fabric, and I don't mean to sound rude, but, isn't using SSH and changing one settings line fairly easy? That is a remote methodForbore
I found Garth Humphreys' approach not great because of browser caching. It led to situations where either: - non maintenance mode pages were seen during maintenance mode - the maintenance mode page was seen when not in maintenance mode I'll put my tweaked solution in a separate answer.Possessory
P
9

Fabric does have commands to help you comment or uncomment lines in a given file in fabric.contrib.files. See the docs here: http://docs.fabfile.org/en/1.0.1/api/contrib/files.html

Personally I prefer to handle this at the front-end proxy rather than in a Django middleware. I would take a look at this question Show a custom 503 page if upstream is down which configures Nginx to use a custom page when the upstream is down.

Plunder answered 10/6, 2011 at 19:13 Comment(4)
but can admin/staff users still get in without 503s? The middleware seems pretty cool, especially for those of us that tend to develop on the production server. The Nginx 503 would be nice when the Django project is actually down though.Forbore
@Forbore there is no reason why you couldn't use both. If the Django server is down then the middleware is not going to work and Nginx would kick in.Plunder
Thanks for the feedback everyone in the end this is what I did and it works great for me, garthhumphreys.com/2011/06/11/… - I do like the idea of uncomment lines but with my setup if I were to do that on the production server it would be overwritten once I pushed the new version out, so in the end putting the site into maintenance mode from the server level and not the django level works a lot better and is truly easier and flexible, for me at least :)Ebby
Sorry @MarkLavin I didn't say thanks for pointing out the comments command in fabric, thanks!Ebby
P
4

My solution:

  1. Create a maintenance mode template and link to it via a urlconf, so when visiting /under-maintenance/ a maintenance page is shown.
  2. Then, configure apache to test for the presence of a 'maintenance-mode-on' file, and if it is present do a 302 redirect to the url of the maintenance mode page.
  3. Configure apache to redirect from the maintenance mode URL to the home page, if the 'maintenance-mode-off' file is present.
  4. Fabric script to facilitate switching the files between maintenance-mode-on and maintenance-mode-off.

Here's the relevant section of the Apache config file:

RewriteEngine On
# If this file (toggle file) exists then put the site into maintenance mode
RewriteCond /path/to/toggle/file/maintenance-mode-on -f
RewriteCond %{REQUEST_URI} !^/static.* 
RewriteCond %{REQUEST_URI} !^/admin.* 
RewriteCond %{REQUEST_URI} !^/under-maintenance/ 
# redirect to the maintenance mode page
RewriteRule ^(.*) /under-maintenance/ [R,L]

#If not under maintenance mode, redirect away from the maintenance page
RewriteCond /path/to/toggle/file/maintenance-mode-off -f
RewriteCond %{REQUEST_URI} ^/under-maintenance/
RewriteRule ^(.*) / [R,L]

Then the relevant parts of the fabric script:

env.var_dir = '/path/to/toggle/file/'

def is_in_mm():
    "Returns whether the site is in maintenance mode"
    return files.exists(os.path.join(env.var_dir, 'maintenance-mode-on'))

@task
def mm_on():
    """Turns on maintenance mode"""
    if not is_in_mm():
        with cd(env.var_dir):
            run('mv maintenance-mode-off maintenance-mode-on')
            utils.fastprint('Turned on maintenance mode.')
    else:
        utils.error('The site is already in maintenance mode!')


@task
def mm_off():
    """Turns off maintenance mode"""
    if is_in_mm():
        with cd(env.var_dir):
            run('mv maintenance-mode-on maintenance-mode-off')
            utils.fastprint('Turned off maintenance mode.')
    else:
        utils.error('The site is not in maintenance mode!')

This works well, though it does depend on Django handling requests during maintenance mode; it would be nice to just serve a static file.

Possessory answered 24/5, 2013 at 11:3 Comment(0)
H
2

There is a fork of django-maintenancemode that allows to turn the maintenance mode on/off by setting a value in database. This way you can, for example, create a simple management command to toggle the maintenance mode and call it via fabric. I think it's more flexible than using mod_rewrite.

Hildahildagard answered 6/9, 2011 at 4:16 Comment(2)
That must mean that every page served through django requires an extra hit to the database?Patriliny
What if the website is in maintenance mode due to works on the database?Forespeak

© 2022 - 2024 — McMap. All rights reserved.