Adding a running method to the Backup Model
* Adds a query classmethod to Base Model for more complex queries such 'in_' * Adds a running classmethod to Backup Model which returns any currently running backups for an instance. * Add a checksum field to the Backup Model. * Refactor the DBBackup to reuse base methods Change-Id: Iaf6903af88c7f4caa20921f1ca63354999ec6348
This commit is contained in:
@@ -16,10 +16,7 @@
|
||||
|
||||
from reddwarf.common import cfg
|
||||
from reddwarf.common import exception
|
||||
from reddwarf.common import utils
|
||||
|
||||
from reddwarf.db.models import DatabaseModelBase
|
||||
|
||||
from reddwarf.openstack.common import log as logging
|
||||
|
||||
CONF = cfg.CONF
|
||||
@@ -33,6 +30,8 @@ class BackupState(object):
|
||||
SAVING = "SAVING"
|
||||
COMPLETED = "COMPLETED"
|
||||
FAILED = "FAILED"
|
||||
RUNNING_STATES = [NEW, BUILDING, SAVING]
|
||||
END_STATES = [COMPLETED, FAILED]
|
||||
|
||||
|
||||
class Backup(object):
|
||||
@@ -60,6 +59,37 @@ class Backup(object):
|
||||
LOG.exception("Unable to create Backup record:")
|
||||
raise exception.BackupCreationError(str(ex))
|
||||
|
||||
@classmethod
|
||||
def running(cls, instance_id, exclude=None):
|
||||
"""
|
||||
Returns the first running backup for instance_id
|
||||
:param instance_id: Id of the instance
|
||||
:param exclude: Backup ID to exclude from the query (any other running)
|
||||
"""
|
||||
query = DBBackup.query()
|
||||
query = query.filter(DBBackup.instance_id == instance_id,
|
||||
DBBackup.state.in_(BackupState.RUNNING_STATES))
|
||||
# filter out deleted backups, PEP8 does not like field == False!
|
||||
query = query.filter_by(deleted=False)
|
||||
if exclude:
|
||||
query = query.filter(DBBackup.id != exclude)
|
||||
return query.first()
|
||||
|
||||
@classmethod
|
||||
def get_by_id(cls, backup_id, deleted=False):
|
||||
"""
|
||||
get the backup for that id
|
||||
:param cls:
|
||||
:param backup_id: Id of the backup to return
|
||||
:param deleted: Return deleted backups
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
db_info = DBBackup.find_by(id=backup_id, deleted=deleted)
|
||||
return db_info
|
||||
except exception.NotFound:
|
||||
raise exception.NotFound(uuid=backup_id)
|
||||
|
||||
@classmethod
|
||||
def list(cls, context):
|
||||
"""
|
||||
@@ -85,22 +115,17 @@ class Backup(object):
|
||||
return db_info
|
||||
|
||||
@classmethod
|
||||
def delete(cls, id):
|
||||
def delete(cls, backup_id):
|
||||
"""
|
||||
update Backup table on deleted flag for given Backup
|
||||
:param cls:
|
||||
:param id: Backup uuid
|
||||
:param backup_id: Backup uuid
|
||||
:return:
|
||||
"""
|
||||
#TODO: api (service.py) might take care of actual deletion
|
||||
# on remote swift
|
||||
try:
|
||||
db_info = DBBackup.find_by(id=id, deleted=False)
|
||||
db_info.update(deleted=True, deleted_at=utils.utcnow())
|
||||
except exception.ReddwarfError as ex:
|
||||
LOG.exception("Backup record cannot be updated for "
|
||||
"backup %s :") % id
|
||||
raise exception.BackupUpdateError(str(ex))
|
||||
db_info = cls.get_by_id(backup_id)
|
||||
db_info.delete()
|
||||
|
||||
|
||||
def persisted_models():
|
||||
@@ -111,5 +136,14 @@ class DBBackup(DatabaseModelBase):
|
||||
"""A table for Backup records"""
|
||||
_data_fields = ['id', 'name', 'description', 'location', 'backup_type',
|
||||
'size', 'tenant_id', 'state', 'instance_id',
|
||||
'backup_timestamp', 'deleted', 'created',
|
||||
'checksum', 'backup_timestamp', 'deleted', 'created',
|
||||
'updated', 'deleted_at']
|
||||
preserve_on_delete = True
|
||||
|
||||
@property
|
||||
def is_running(self):
|
||||
return self.state in BackupState.RUNNING_STATES
|
||||
|
||||
@property
|
||||
def is_done(self):
|
||||
return self.state in BackupState.END_STATES
|
||||
|
||||
@@ -47,6 +47,10 @@ class DatabaseModelBase(models.ModelBase):
|
||||
def preserve_on_delete(self):
|
||||
return hasattr(self, 'deleted') and hasattr(self, 'deleted_at')
|
||||
|
||||
@classmethod
|
||||
def query(cls):
|
||||
return get_db_api()._base_query(cls)
|
||||
|
||||
def save(self):
|
||||
if not self.is_valid():
|
||||
raise exception.InvalidModelError(errors=self.errors)
|
||||
|
||||
@@ -36,6 +36,7 @@ backups = Table('backups', meta,
|
||||
Column('tenant_id', String(36)),
|
||||
Column('state', String(32), nullable=False),
|
||||
Column('instance_id', String(36)),
|
||||
Column('checksum', String(32)),
|
||||
Column('backup_timestamp', DateTime()),
|
||||
Column('deleted', Boolean()),
|
||||
Column('created', DateTime()),
|
||||
|
||||
@@ -57,11 +57,11 @@ class BackupORMTest(testtools.TestCase):
|
||||
super(BackupORMTest, self).setUp()
|
||||
util.init_db()
|
||||
self.context, self.instance_id = _prep_conf(utils.utcnow())
|
||||
models.DBBackup.create(tenant_id=self.context.tenant,
|
||||
name=BACKUP_NAME,
|
||||
state=BACKUP_STATE,
|
||||
instance_id=self.instance_id,
|
||||
deleted=False)
|
||||
self.backup = models.DBBackup.create(tenant_id=self.context.tenant,
|
||||
name=BACKUP_NAME,
|
||||
state=BACKUP_STATE,
|
||||
instance_id=self.instance_id,
|
||||
deleted=False)
|
||||
self.deleted = False
|
||||
|
||||
def tearDown(self):
|
||||
@@ -82,11 +82,45 @@ class BackupORMTest(testtools.TestCase):
|
||||
db_record = models.Backup.list_for_instance(self.instance_id)
|
||||
self.assertEqual(2, db_record.count())
|
||||
|
||||
def test_running(self):
|
||||
running = models.Backup.running(instance_id=self.instance_id)
|
||||
self.assertTrue(running)
|
||||
|
||||
def test_not_running(self):
|
||||
not_running = models.Backup.running(instance_id='non-existent')
|
||||
self.assertFalse(not_running)
|
||||
|
||||
def test_running_exclude(self):
|
||||
not_running = models.Backup.running(instance_id=self.instance_id,
|
||||
exclude=self.backup.id)
|
||||
self.assertFalse(not_running)
|
||||
|
||||
def test_is_running(self):
|
||||
self.assertTrue(self.backup.is_running)
|
||||
|
||||
def test_is_done(self):
|
||||
self.backup.state = models.BackupState.COMPLETED
|
||||
self.backup.save()
|
||||
self.assertTrue(self.backup.is_done)
|
||||
|
||||
def test_not_is_running(self):
|
||||
self.backup.state = models.BackupState.COMPLETED
|
||||
self.backup.save()
|
||||
self.assertFalse(self.backup.is_running)
|
||||
|
||||
def test_not_is_done(self):
|
||||
self.assertFalse(self.backup.is_done)
|
||||
|
||||
def test_backup_delete(self):
|
||||
models.Backup.delete(self.backup.id)
|
||||
query = models.Backup.list_for_instance(self.instance_id)
|
||||
self.assertEqual(query.count(), 0)
|
||||
|
||||
def test_delete(self):
|
||||
db_record = models.DBBackup.find_by(tenant_id=self.context.tenant)
|
||||
uuid = db_record['id']
|
||||
print uuid
|
||||
models.Backup.delete(uuid)
|
||||
self.deleted = True
|
||||
db_record = models.DBBackup.find_by(id=uuid, deleted=True)
|
||||
self.backup.delete()
|
||||
db_record = models.DBBackup.find_by(id=self.backup.id, deleted=True)
|
||||
self.assertEqual(self.instance_id, db_record['instance_id'])
|
||||
|
||||
def test_deleted_not_running(self):
|
||||
self.backup.delete()
|
||||
self.assertFalse(models.Backup.running(self.instance_id))
|
||||
|
||||
Reference in New Issue
Block a user