Source

django-swingcms / swingcms / cms / management / commands / backup.py

Full commit
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
from subprocess import check_call, CalledProcessError

from django.core.management.base import BaseCommand, CommandError

import settings

from cms.code import zipper
from cms.models import ds, Logger



SITE_BACKUP_PATH = os.path.join(settings.BACKUP_PATH, '%s.%s' % (settings.DOMAIN, settings.SECRET_KEY))

class Command(BaseCommand):
    """
    Backup entire site or only db and stored files, depending of mode.
    Default backup folder is /var/backups plus site names and specific installation tokens.
    Require rdiff-backup installed. Prepare .zip file and cleaning old backups.
    """

    help = "Execute backup."
    requires_model_validation = False

    def handle(self, *args, **options):

        if not ds.SITE_STATUS == 'UP':
            raise CommandError("Site is not UP.")
        try:
            ds.SITE_STATUS = 'LOCK'

            # backup
            if 'complete' in args:
                args = ('--force',
                        settings.ROOT,
                        SITE_BACKUP_PATH)
            elif 'minimal' in args:
                args = ('--force',
                        '--include', settings.MEDIA_ROOT,
                        '--include', settings.DATABASES['default']['NAME'],
                        '--exclude', '**',
                        settings.ROOT,
                        SITE_BACKUP_PATH)
            else:
                raise CommandError("Not supported mode.")

            errors = ''

            command = ("rdiff-backup",) + args
            try:
                p = check_call(command, shell=False)
            except Exception, e:
                if isinstance(e, CalledProcessError):
                    e = e.returncode
                errors = "Error in execute rdiff-backup command: no backup finalized."
                if settings.VERBOSE:
                    print "COMMAND: ", " ".join(command)

            # zip
            if not errors:
                try:
                    zf = zipper(SITE_BACKUP_PATH, SITE_BACKUP_PATH + ".zip")
                    zf.close()
                except Exception, e:
                    errors += "\nError in execute rdiff-backup command: no zipping finalized."

            # clean
            args = ('--remove-older-than', '4W',
                    SITE_BACKUP_PATH)
            command = ('rdiff-backup',) + args
            try:
                p = check_call(command, shell=False)
            except Exception, e:
                if isinstance(e, CalledProcessError):
                    e = e.returncode
                errors += "\nError in execute rdiff-backup command: no cleaning old data finalized."
                if settings.VERBOSE:
                    print "COMMAND: ", " ".join(command)

            if errors:
                raise CommandError(errors)

        except Exception, e:
            if settings.VERBOSE:
                print "FAIL: %s" % unicode(e)
            raise CommandError(e)

        finally:
            ds.SITE_STATUS = 'UP'