From 29654c5f997e5ce7e4555133ffaec76941eed087 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 17 Aug 2012 03:32:11 -0400 Subject: [PATCH] Update backup app api, add new LocalFilesystemStorage, show apps in backup list --- apps/backups/api.py | 64 ++++++++++++++++++++++++++++++++---------- apps/backups/models.py | 4 +-- apps/backups/views.py | 13 +++++---- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/apps/backups/api.py b/apps/backups/api.py index d2b9c24d3b..a9b5a38b89 100644 --- a/apps/backups/api.py +++ b/apps/backups/api.py @@ -1,11 +1,12 @@ import logging import os -from django.utils.translation import ugettext_lazy as _ -from django.utils.translation import ugettext from django.core.files.base import ContentFile +from django.core.files.storage import FileSystemStorage from django.core.management.commands.dumpdata import Command from django.db import router, DEFAULT_DB_ALIAS +from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext logger = logging.getLogger(__name__) @@ -38,7 +39,7 @@ class Fixture(ElementDataBase): @property def filename(self): - return '%s_%s' % (self.__class__.name, self.model_backup.app_backup.app) + return '%s_%s' % (self.model_backup.app_backup.app, self.__class__.name) def save(self): return ContentFile(name=self.filename, content=self.content) @@ -93,10 +94,10 @@ class ModelBackup(ElementBackupBase): #TODO: a single Fixture or a list of Fixtures for each model? #Can't return multiple Fixture until a way to find all of an app's models is found - return Fixture( + return [Fixture( model_backup=self, content=command.handle(u' '.join(result), format='json', indent=4, using=DEFAULT_DB_ALIAS, exclude=[], user_base_manager=False, use_natural_keys=False) - ) + )] class FileBackup(ElementBackupBase): @@ -236,8 +237,11 @@ class StorageModuleBase(object): def __unicode__(self): return unicode(self.label) + #def __init__(self, *args, **kwargs): + # self.dry_run = kwargs.pop('dry_run', False) -class TestStorageModule(StorageModuleBase): + +class TestStorage(StorageModuleBase): name = 'test_storage' label = _(u'Test storage module') realm = StorageModuleBase.REALM_LOCAL @@ -249,18 +253,48 @@ class TestStorageModule(StorageModuleBase): def get_arguments(self): return ['backup_path', 'restore_path'] - def backup(self, data, dry_run): - print '***** received data' - #print data.content - #print 'name', data.filename - print '***** saving to path: %s' % self.backup_path - result = data.save() - with open(os.path.join(self.backup_path, result.name), 'w') as descriptor: - descriptor.write(result.read()) + def backup(self, elements, dry_run): + logger.debug('self.backup_path: %s' % self.backup_path) + + for element in elements: + content_file = element.save() + logger.debug('element.filename: %s' % element.filename) + logger.debug('element.content: %s' % element.content) def restore(self): print 'restore from path: %s' % self.restore_path return 'sample_data' -StorageModuleBase.register(TestStorageModule) +class LocalFileSystemStorage(FileSystemStorage): + """ + Simple wrapper for the stock Django FileSystemStorage class + """ + name = 'local_filesystem_storage' + label = _(u'Local filesystem') + realm = StorageModuleBase.REALM_LOCAL + + separator = os.path.sep + + def get_arguments(self): + return ['backup_path', 'restore_path'] + + def backup(self, elements, dry_run): + logger.debug('self.backup_path: %s' % self.backup_path) + for element in elements: + content_file = element.save() + path = self.storage.save(content_file.name, content_file) + logger.debug('element.filename: %s' % element.filename) + logger.debug('element.content: %s' % element.content) + + def restore(self): + print 'restore from path: %s' % self.restore_path + return 'sample_data' + + def __init__(self, *args, **kwargs): + self.backup_path = kwargs.pop('backup_path', None) + self.storage = FileSystemStorage(location=self.backup_path) + + +StorageModuleBase.register(LocalFileSystemStorage) +StorageModuleBase.register(TestStorage) diff --git a/apps/backups/models.py b/apps/backups/models.py index 5a5dafeae3..618e34989f 100644 --- a/apps/backups/models.py +++ b/apps/backups/models.py @@ -34,7 +34,7 @@ class BackupJob(models.Model): # * type # - Full # - Incremental - storage_module_name = models.CharField(max_length=16, choices=StorageModuleBase.get_as_choices(), verbose_name=_(u'storage module')) + storage_module_name = models.CharField(max_length=32, choices=StorageModuleBase.get_as_choices(), verbose_name=_(u'storage module')) storage_arguments_json = models.TextField(verbose_name=_(u'storage module arguments (in JSON)'), blank=True) def __unicode__(self): @@ -51,7 +51,7 @@ class BackupJob(models.Model): #TODO: loads for app in self.apps.all(): app_backup = AppBackup.get(app) - app_backup.backup(storage_module(backup_path='/tmp', dry_run=dry_run), dry_run=dry_run) + app_backup.backup(storage_module(backup_path='/tmp'), dry_run=dry_run) def save(self, *args, **kwargs): #dump diff --git a/apps/backups/views.py b/apps/backups/views.py index 7e46de7445..53dba58329 100644 --- a/apps/backups/views.py +++ b/apps/backups/views.py @@ -6,10 +6,11 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.contrib import messages from django.core.urlresolvers import reverse +from django.conf import settings from permissions.models import Permission -from .api import AppBackup, TestStorageModule +from .api import AppBackup from .forms import BackupJobForm from .models import BackupJob from .permissions import PERMISSION_BACKUP_JOB_VIEW, PERMISSION_BACKUP_JOB_CREATE, PERMISSION_BACKUP_JOB_EDIT @@ -99,8 +100,11 @@ def backup_job_test(request, backup_job_pk): try: backup_job.backup(dry_run=True) except Exception, exc: - messages.error(request, _(u'Error testing backup job; %s') % exc) - return HttpResponseRedirect(reverse('backup_job_list')) + if settings.DEBUG: + raise + else: + messages.error(request, _(u'Error testing backup job; %s') % exc) + return HttpResponseRedirect(reverse('backup_job_list')) else: messages.success(request, _(u'Test for backup job "%s" finished successfully.') % backup_job) return HttpResponseRedirect(reverse('backup_job_list')) @@ -117,8 +121,5 @@ def backup_view(request): {'name': _(u'info'), 'attribute': 'info'}, ], } - # TODO: move to test.py - #ab = AppBackup.get_all()[0] - #ab.backup(TestStorageModule(backup_path = '/tmp')) return render_to_response('generic_list.html', context, context_instance=RequestContext(request))