Update OVO instance on destroy method call
None of the Versioned Objects destroy methods we have update the instance fields, so after doing a destroy on an instance the status, deleted, and deleted_at fields will still be the same as they were before, leaving the instance in an inconsistent state. This is important because our workers decorator for the HA A-A cleanup mechanism relies on the status of the resources being properly updated by the operations. Change-Id: I4f15356931007e2ca725e477327c1ef67c7db487 Closes-Bug: #1604347
This commit is contained in:
parent
6cfecade9e
commit
b03f539e6e
@ -407,8 +407,10 @@ def _service_query(context, session=None, read_deleted='no', host=None,
|
||||
@require_admin_context
|
||||
def service_destroy(context, service_id):
|
||||
query = _service_query(context, id=service_id)
|
||||
if not query.update(models.Service.delete_values()):
|
||||
updated_values = models.Service.delete_values()
|
||||
if not query.update(updated_values):
|
||||
raise exception.ServiceNotFound(service_id=service_id)
|
||||
return updated_values
|
||||
|
||||
|
||||
@require_admin_context
|
||||
@ -614,7 +616,7 @@ def quota_destroy(context, project_id, resource):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
quota_ref = _quota_get(context, project_id, resource, session=session)
|
||||
quota_ref.delete(session=session)
|
||||
return quota_ref.delete(session=session)
|
||||
|
||||
|
||||
###################
|
||||
@ -717,7 +719,7 @@ def quota_class_destroy(context, class_name, resource):
|
||||
with session.begin():
|
||||
quota_class_ref = _quota_class_get(context, class_name, resource,
|
||||
session=session)
|
||||
quota_class_ref.delete(session=session)
|
||||
return quota_class_ref.delete(session=session)
|
||||
|
||||
|
||||
@require_admin_context
|
||||
@ -1287,13 +1289,14 @@ def volume_destroy(context, volume_id):
|
||||
session = get_session()
|
||||
now = timeutils.utcnow()
|
||||
with session.begin():
|
||||
model_query(context, models.Volume, session=session).\
|
||||
filter_by(id=volume_id).\
|
||||
update({'status': 'deleted',
|
||||
updated_values = {'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': now,
|
||||
'updated_at': literal_column('updated_at'),
|
||||
'migration_status': None})
|
||||
'migration_status': None}
|
||||
model_query(context, models.Volume, session=session).\
|
||||
filter_by(id=volume_id).\
|
||||
update(updated_values)
|
||||
model_query(context, models.VolumeMetadata, session=session).\
|
||||
filter_by(volume_id=volume_id).\
|
||||
update({'deleted': True,
|
||||
@ -1309,6 +1312,8 @@ def volume_destroy(context, volume_id):
|
||||
update({'deleted': True,
|
||||
'deleted_at': now,
|
||||
'updated_at': literal_column('updated_at')})
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
@require_admin_context
|
||||
@ -2208,19 +2213,23 @@ def snapshot_create(context, values):
|
||||
@require_admin_context
|
||||
@_retry_on_deadlock
|
||||
def snapshot_destroy(context, snapshot_id):
|
||||
utcnow = timeutils.utcnow()
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
updated_values = {'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')}
|
||||
model_query(context, models.Snapshot, session=session).\
|
||||
filter_by(id=snapshot_id).\
|
||||
update({'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
update(updated_values)
|
||||
model_query(context, models.SnapshotMetadata, session=session).\
|
||||
filter_by(snapshot_id=snapshot_id).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')})
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
@require_context
|
||||
@ -2928,6 +2937,7 @@ def volume_type_qos_specs_get(context, type_id):
|
||||
@require_admin_context
|
||||
@_retry_on_deadlock
|
||||
def volume_type_destroy(context, id):
|
||||
utcnow = timeutils.utcnow()
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
_volume_type_get(context, id, session)
|
||||
@ -2937,19 +2947,22 @@ def volume_type_destroy(context, id):
|
||||
LOG.error(_LE('VolumeType %s deletion failed, '
|
||||
'VolumeType in use.'), id)
|
||||
raise exception.VolumeTypeInUse(volume_type_id=id)
|
||||
updated_values = {'deleted': True,
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')}
|
||||
model_query(context, models.VolumeTypes, session=session).\
|
||||
filter_by(id=id).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
update(updated_values)
|
||||
model_query(context, models.VolumeTypeExtraSpecs, session=session).\
|
||||
filter_by(volume_type_id=id).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')})
|
||||
model_query(context, models.VolumeTypeProjects, session=session,
|
||||
read_deleted="int_no").filter_by(
|
||||
volume_type_id=id).soft_delete(synchronize_session=False)
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
@require_context
|
||||
@ -3357,13 +3370,16 @@ def qos_specs_delete(context, qos_specs_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
_qos_specs_get_ref(context, qos_specs_id, session)
|
||||
updated_values = {'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')}
|
||||
session.query(models.QualityOfServiceSpecs).\
|
||||
filter(or_(models.QualityOfServiceSpecs.id == qos_specs_id,
|
||||
models.QualityOfServiceSpecs.specs_id ==
|
||||
qos_specs_id)).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
update(updated_values)
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
@require_admin_context
|
||||
@ -3868,12 +3884,15 @@ def backup_update(context, backup_id, values):
|
||||
|
||||
@require_admin_context
|
||||
def backup_destroy(context, backup_id):
|
||||
model_query(context, models.Backup).\
|
||||
filter_by(id=backup_id).\
|
||||
update({'status': fields.BackupStatus.DELETED,
|
||||
updated_values = {'status': fields.BackupStatus.DELETED,
|
||||
'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
'updated_at': literal_column('updated_at')}
|
||||
model_query(context, models.Backup).\
|
||||
filter_by(id=backup_id).\
|
||||
update(updated_values)
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
###############################
|
||||
@ -3959,6 +3978,7 @@ def transfer_create(context, values):
|
||||
@require_context
|
||||
@_retry_on_deadlock
|
||||
def transfer_destroy(context, transfer_id):
|
||||
utcnow = timeutils.utcnow()
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
transfer_ref = _transfer_get(context,
|
||||
@ -3976,11 +3996,16 @@ def transfer_destroy(context, transfer_id):
|
||||
volume_ref['status'] = 'available'
|
||||
volume_ref.update(volume_ref)
|
||||
volume_ref.save(session=session)
|
||||
updated_values = {'deleted': True,
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')}
|
||||
model_query(context, models.Transfer, session=session).\
|
||||
filter_by(id=transfer_id).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')})
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
@require_context
|
||||
@ -4204,14 +4229,21 @@ def consistencygroup_update(context, consistencygroup_id, values):
|
||||
|
||||
@require_admin_context
|
||||
def consistencygroup_destroy(context, consistencygroup_id):
|
||||
utcnow = timeutils.utcnow()
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
updated_values = {'status': fields.ConsistencyGroupStatus.DELETED,
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')}
|
||||
model_query(context, models.ConsistencyGroup, session=session).\
|
||||
filter_by(id=consistencygroup_id).\
|
||||
update({'status': fields.ConsistencyGroupStatus.DELETED,
|
||||
'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'deleted_at': utcnow,
|
||||
'updated_at': literal_column('updated_at')})
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
def cg_has_cgsnapshot_filter():
|
||||
@ -4406,12 +4438,15 @@ def cgsnapshot_update(context, cgsnapshot_id, values):
|
||||
def cgsnapshot_destroy(context, cgsnapshot_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
model_query(context, models.Cgsnapshot, session=session).\
|
||||
filter_by(id=cgsnapshot_id).\
|
||||
update({'status': 'deleted',
|
||||
updated_values = {'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
'updated_at': literal_column('updated_at')}
|
||||
model_query(context, models.Cgsnapshot, session=session).\
|
||||
filter_by(id=cgsnapshot_id).\
|
||||
update(updated_values)
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
def cgsnapshot_creating_from_src():
|
||||
@ -4587,11 +4622,14 @@ def message_destroy(context, message):
|
||||
session = get_session()
|
||||
now = timeutils.utcnow()
|
||||
with session.begin():
|
||||
updated_values = {'deleted': True,
|
||||
'deleted_at': now,
|
||||
'updated_at': literal_column('updated_at')}
|
||||
(model_query(context, models.Message, session=session).
|
||||
filter_by(id=message.get('id')).
|
||||
update({'deleted': True,
|
||||
'deleted_at': now,
|
||||
'updated_at': literal_column('updated_at')}))
|
||||
update(updated_values))
|
||||
del updated_values['updated_at']
|
||||
return updated_values
|
||||
|
||||
|
||||
###############################
|
||||
|
@ -52,8 +52,10 @@ class CinderBase(models.TimestampMixin,
|
||||
|
||||
def delete(self, session):
|
||||
"""Delete this object."""
|
||||
self.update(self.delete_values())
|
||||
updated_values = self.delete_values()
|
||||
self.update(updated_values)
|
||||
self.save(session=session)
|
||||
return updated_values
|
||||
|
||||
|
||||
class Service(BASE, CinderBase):
|
||||
|
@ -122,7 +122,9 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
def destroy(self):
|
||||
with self.obj_as_admin():
|
||||
db.backup_destroy(self._context, self.id)
|
||||
updated_values = db.backup_destroy(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
@staticmethod
|
||||
def decode_record(backup_url):
|
||||
|
@ -114,7 +114,9 @@ class CGSnapshot(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
def destroy(self):
|
||||
with self.obj_as_admin():
|
||||
db.cgsnapshot_destroy(self._context, self.id)
|
||||
updated_values = db.cgsnapshot_destroy(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
|
||||
@base.CinderObjectRegistry.register
|
||||
|
@ -136,7 +136,10 @@ class ConsistencyGroup(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
def destroy(self):
|
||||
with self.obj_as_admin():
|
||||
db.consistencygroup_destroy(self._context, self.id)
|
||||
updated_values = db.consistencygroup_destroy(self._context,
|
||||
self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
|
||||
@base.CinderObjectRegistry.register
|
||||
|
@ -169,10 +169,11 @@ class QualityOfServiceSpecs(base.CinderPersistentObject,
|
||||
if self.volume_types:
|
||||
if not force:
|
||||
raise exception.QoSSpecsInUse(specs_id=self.id)
|
||||
else:
|
||||
# remove all association
|
||||
db.qos_specs_disassociate_all(self._context, self.id)
|
||||
db.qos_specs_delete(self._context, self.id)
|
||||
updated_values = db.qos_specs_delete(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
|
||||
@base.CinderObjectRegistry.register
|
||||
|
@ -95,7 +95,9 @@ class Service(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
def destroy(self):
|
||||
with self.obj_as_admin():
|
||||
db.service_destroy(self._context, self.id)
|
||||
updated_values = db.service_destroy(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
@classmethod
|
||||
def _get_minimum_version(cls, attribute, context, binary):
|
||||
|
@ -178,7 +178,9 @@ class Snapshot(base.CinderPersistentObject, base.CinderObject,
|
||||
self.obj_reset_changes()
|
||||
|
||||
def destroy(self):
|
||||
db.snapshot_destroy(self._context, self.id)
|
||||
updated_values = db.snapshot_destroy(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
if attrname not in self.OPTIONAL_FIELDS:
|
||||
|
@ -327,7 +327,9 @@ class Volume(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
def destroy(self):
|
||||
with self.obj_as_admin():
|
||||
db.volume_destroy(self._context, self.id)
|
||||
updated_values = db.volume_destroy(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
if attrname not in self.OPTIONAL_FIELDS:
|
||||
|
@ -115,7 +115,9 @@ class VolumeType(base.CinderPersistentObject, base.CinderObject,
|
||||
|
||||
def destroy(self):
|
||||
with self.obj_as_admin():
|
||||
volume_types.destroy(self._context, self.id)
|
||||
updated_values = volume_types.destroy(self._context, self.id)
|
||||
self.update(updated_values)
|
||||
self.obj_reset_changes(updated_values.keys())
|
||||
|
||||
|
||||
@base.CinderObjectRegistry.register
|
||||
|
@ -13,6 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder.db.sqlalchemy import models
|
||||
@ -77,13 +79,22 @@ class TestBackup(test_objects.BaseObjectsTestCase):
|
||||
backup_update.assert_called_once_with(self.context, backup.id,
|
||||
{'display_name': 'foobar'})
|
||||
|
||||
@mock.patch('cinder.db.backup_destroy')
|
||||
def test_destroy(self, backup_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.backup_destroy')
|
||||
def test_destroy(self, backup_destroy, utcnow_mock):
|
||||
backup_destroy.return_value = {
|
||||
'status': fields.BackupStatus.DELETED,
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
backup = objects.Backup(context=self.context, id=fake.BACKUP_ID)
|
||||
backup.destroy()
|
||||
self.assertTrue(backup_destroy.called)
|
||||
admin_context = backup_destroy.call_args[0][0]
|
||||
self.assertTrue(admin_context.is_admin)
|
||||
self.assertTrue(backup.deleted)
|
||||
self.assertEqual(fields.BackupStatus.DELETED, backup.status)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
backup.deleted_at)
|
||||
|
||||
def test_obj_field_temp_volume_snapshot_id(self):
|
||||
backup = objects.Backup(context=self.context,
|
||||
|
@ -13,6 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder import exception
|
||||
@ -81,14 +83,23 @@ class TestCGSnapshot(test_objects.BaseObjectsTestCase):
|
||||
cgsnapshot.obj_get_changes())
|
||||
self.assertRaises(exception.ObjectActionError, cgsnapshot.save)
|
||||
|
||||
@mock.patch('cinder.db.cgsnapshot_destroy')
|
||||
def test_destroy(self, cgsnapshot_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.cgsnapshot_destroy')
|
||||
def test_destroy(self, cgsnapshot_destroy, utcnow_mock):
|
||||
cgsnapshot_destroy.return_value = {
|
||||
'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
cgsnapshot = objects.CGSnapshot(context=self.context,
|
||||
id=fake.CGSNAPSHOT_ID)
|
||||
cgsnapshot.destroy()
|
||||
self.assertTrue(cgsnapshot_destroy.called)
|
||||
admin_context = cgsnapshot_destroy.call_args[0][0]
|
||||
self.assertTrue(admin_context.is_admin)
|
||||
self.assertTrue(cgsnapshot.deleted)
|
||||
self.assertEqual('deleted', cgsnapshot.status)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
cgsnapshot.deleted_at)
|
||||
|
||||
@mock.patch('cinder.objects.consistencygroup.ConsistencyGroup.get_by_id')
|
||||
@mock.patch('cinder.objects.snapshot.SnapshotList.get_all_for_cgsnapshot')
|
||||
|
@ -13,6 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder import exception
|
||||
@ -146,14 +148,24 @@ class TestConsistencyGroup(test_objects.BaseObjectsTestCase):
|
||||
mock_vol_get_all_by_group.assert_called_once_with(self.context,
|
||||
consistencygroup.id)
|
||||
|
||||
@mock.patch('cinder.db.consistencygroup_destroy')
|
||||
def test_destroy(self, consistencygroup_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.consistencygroup_destroy')
|
||||
def test_destroy(self, consistencygroup_destroy, utcnow_mock):
|
||||
consistencygroup_destroy.return_value = {
|
||||
'status': fields.ConsistencyGroupStatus.DELETED,
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
consistencygroup = objects.ConsistencyGroup(
|
||||
context=self.context, id=fake.CONSISTENCY_GROUP_ID)
|
||||
consistencygroup.destroy()
|
||||
self.assertTrue(consistencygroup_destroy.called)
|
||||
admin_context = consistencygroup_destroy.call_args[0][0]
|
||||
self.assertTrue(admin_context.is_admin)
|
||||
self.assertTrue(consistencygroup.deleted)
|
||||
self.assertEqual(fields.ConsistencyGroupStatus.DELETED,
|
||||
consistencygroup.status)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
consistencygroup.deleted_at)
|
||||
|
||||
@mock.patch('cinder.db.sqlalchemy.api.consistencygroup_get')
|
||||
def test_refresh(self, consistencygroup_get):
|
||||
|
@ -11,6 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
|
||||
from cinder.db.sqlalchemy import models
|
||||
from cinder import exception
|
||||
@ -78,17 +80,25 @@ class TestQos(test_objects.BaseObjectsTestCase):
|
||||
mock.call(self.context, fake.OBJECT_ID, 'key_to_remove1'),
|
||||
mock.call(self.context, fake.OBJECT_ID, 'key_to_remove2')])
|
||||
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.objects.VolumeTypeList.get_all_types_for_qos',
|
||||
return_value=None)
|
||||
@mock.patch('cinder.db.qos_specs_delete')
|
||||
def test_destroy_no_vol_types(self, qos_fake_delete, fake_get_vol_types):
|
||||
@mock.patch('cinder.db.sqlalchemy.api.qos_specs_delete')
|
||||
def test_destroy_no_vol_types(self, qos_fake_delete, fake_get_vol_types,
|
||||
utcnow_mock):
|
||||
qos_fake_delete.return_value = {
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
qos_object = objects.QualityOfServiceSpecs._from_db_object(
|
||||
self.context, objects.QualityOfServiceSpecs(), fake_qos)
|
||||
qos_object.destroy()
|
||||
|
||||
qos_fake_delete.assert_called_once_with(self.context, fake_qos['id'])
|
||||
qos_fake_delete.assert_called_once_with(mock.ANY, fake_qos['id'])
|
||||
self.assertTrue(qos_object.deleted)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
qos_object.deleted_at)
|
||||
|
||||
@mock.patch('cinder.db.qos_specs_delete')
|
||||
@mock.patch('cinder.db.sqlalchemy.api.qos_specs_delete')
|
||||
@mock.patch('cinder.db.qos_specs_disassociate_all')
|
||||
@mock.patch('cinder.objects.VolumeTypeList.get_all_types_for_qos')
|
||||
def test_destroy_with_vol_types(self, fake_get_vol_types,
|
||||
@ -100,7 +110,7 @@ class TestQos(test_objects.BaseObjectsTestCase):
|
||||
self.assertRaises(exception.QoSSpecsInUse, qos_object.destroy)
|
||||
|
||||
qos_object.destroy(force=True)
|
||||
qos_fake_delete.assert_called_once_with(self.context, fake_qos['id'])
|
||||
qos_fake_delete.assert_called_once_with(mock.ANY, fake_qos['id'])
|
||||
qos_fake_disassociate.assert_called_once_with(
|
||||
self.context, fake_qos['id'])
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder import objects
|
||||
@ -69,14 +71,21 @@ class TestService(test_objects.BaseObjectsTestCase):
|
||||
service_update.assert_called_once_with(self.context, service.id,
|
||||
{'topic': 'foobar'})
|
||||
|
||||
@mock.patch('cinder.db.service_destroy')
|
||||
def test_destroy(self, service_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.service_destroy')
|
||||
def test_destroy(self, service_destroy, utcnow_mock):
|
||||
service_destroy.return_value = {
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
db_service = fake_service.fake_db_service()
|
||||
service = objects.Service._from_db_object(
|
||||
self.context, objects.Service(), db_service)
|
||||
with mock.patch.object(service._context, 'elevated') as elevated_ctx:
|
||||
service.destroy()
|
||||
service_destroy.assert_called_once_with(elevated_ctx(), 123)
|
||||
self.assertTrue(service.deleted)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
service.deleted_at)
|
||||
|
||||
@mock.patch('cinder.db.sqlalchemy.api.service_get')
|
||||
def test_refresh(self, service_get):
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
import copy
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder.db.sqlalchemy import models
|
||||
@ -112,12 +114,21 @@ class TestSnapshot(test_objects.BaseObjectsTestCase):
|
||||
{'key1': 'value1'},
|
||||
True)
|
||||
|
||||
@mock.patch('cinder.db.snapshot_destroy')
|
||||
def test_destroy(self, snapshot_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.snapshot_destroy')
|
||||
def test_destroy(self, snapshot_destroy, utcnow_mock):
|
||||
snapshot_destroy.return_value = {
|
||||
'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
snapshot = objects.Snapshot(context=self.context, id=fake.SNAPSHOT_ID)
|
||||
snapshot.destroy()
|
||||
snapshot_destroy.assert_called_once_with(self.context,
|
||||
fake.SNAPSHOT_ID)
|
||||
self.assertTrue(snapshot.deleted)
|
||||
self.assertEqual('deleted', snapshot.status)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
snapshot.deleted_at)
|
||||
|
||||
@mock.patch('cinder.db.snapshot_metadata_delete')
|
||||
def test_delete_metadata_key(self, snapshot_metadata_delete):
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder import context
|
||||
@ -132,8 +134,13 @@ class TestVolume(test_objects.BaseObjectsTestCase):
|
||||
volume.snapshots = objects.SnapshotList()
|
||||
self.assertRaises(exception.ObjectActionError, volume.save)
|
||||
|
||||
@mock.patch('cinder.db.volume_destroy')
|
||||
def test_destroy(self, volume_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.volume_destroy')
|
||||
def test_destroy(self, volume_destroy, utcnow_mock):
|
||||
volume_destroy.return_value = {
|
||||
'status': 'deleted',
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
db_volume = fake_volume.fake_db_volume()
|
||||
volume = objects.Volume._from_db_object(self.context,
|
||||
objects.Volume(), db_volume)
|
||||
@ -141,6 +148,11 @@ class TestVolume(test_objects.BaseObjectsTestCase):
|
||||
self.assertTrue(volume_destroy.called)
|
||||
admin_context = volume_destroy.call_args[0][0]
|
||||
self.assertTrue(admin_context.is_admin)
|
||||
self.assertTrue(volume.deleted)
|
||||
self.assertEqual('deleted', volume.status)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
volume.deleted_at)
|
||||
self.assertIsNone(volume.migration_status)
|
||||
|
||||
def test_obj_fields(self):
|
||||
volume = objects.Volume(context=self.context, id=fake.VOLUME_ID,
|
||||
|
@ -13,6 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
import pytz
|
||||
import six
|
||||
|
||||
from cinder import objects
|
||||
@ -79,8 +81,12 @@ class TestVolumeType(test_objects.BaseObjectsTestCase):
|
||||
volume_type.name,
|
||||
volume_type.description)
|
||||
|
||||
@mock.patch('cinder.volume.volume_types.destroy')
|
||||
def test_destroy(self, volume_type_destroy):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
|
||||
@mock.patch('cinder.db.sqlalchemy.api.volume_type_destroy')
|
||||
def test_destroy(self, volume_type_destroy, utcnow_mock):
|
||||
volume_type_destroy.return_value = {
|
||||
'deleted': True,
|
||||
'deleted_at': utcnow_mock.return_value}
|
||||
db_volume_type = fake_volume.fake_db_volume_type()
|
||||
volume_type = objects.VolumeType._from_db_object(self.context,
|
||||
objects.VolumeType(),
|
||||
@ -89,6 +95,9 @@ class TestVolumeType(test_objects.BaseObjectsTestCase):
|
||||
self.assertTrue(volume_type_destroy.called)
|
||||
admin_context = volume_type_destroy.call_args[0][0]
|
||||
self.assertTrue(admin_context.is_admin)
|
||||
self.assertTrue(volume_type.deleted)
|
||||
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
|
||||
volume_type.deleted_at)
|
||||
|
||||
@mock.patch('cinder.db.sqlalchemy.api._volume_type_get_full')
|
||||
def test_refresh(self, volume_type_get):
|
||||
|
@ -19,6 +19,7 @@ import datetime
|
||||
import enum
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
|
||||
@ -38,6 +39,7 @@ CONF = cfg.CONF
|
||||
THREE = 3
|
||||
THREE_HUNDREDS = 300
|
||||
ONE_HUNDREDS = 100
|
||||
UTC_NOW = timeutils.utcnow()
|
||||
|
||||
|
||||
def _quota_reserve(context, project_id):
|
||||
@ -142,11 +144,14 @@ class DBAPIServiceTestCase(BaseTest):
|
||||
for key, value in self._get_base_values().items():
|
||||
self.assertEqual(value, service[key])
|
||||
|
||||
def test_service_destroy(self):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=UTC_NOW)
|
||||
def test_service_destroy(self, utcnow_mock):
|
||||
service1 = self._create_service({})
|
||||
service2 = self._create_service({'host': 'fake_host2'})
|
||||
|
||||
db.service_destroy(self.ctxt, service1['id'])
|
||||
self.assertDictEqual(
|
||||
{'deleted': True, 'deleted_at': UTC_NOW},
|
||||
db.service_destroy(self.ctxt, service1['id']))
|
||||
self.assertRaises(exception.ServiceNotFound,
|
||||
db.service_get, self.ctxt, service1['id'])
|
||||
self._assertEqualObjects(
|
||||
@ -393,9 +398,13 @@ class DBAPIVolumeTestCase(BaseTest):
|
||||
self._assertEqualObjects(volume, db.volume_get(self.ctxt,
|
||||
volume['id']))
|
||||
|
||||
def test_volume_destroy(self):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=UTC_NOW)
|
||||
def test_volume_destroy(self, utcnow_mock):
|
||||
volume = db.volume_create(self.ctxt, {})
|
||||
db.volume_destroy(self.ctxt, volume['id'])
|
||||
self.assertDictEqual(
|
||||
{'status': 'deleted', 'deleted': True, 'deleted_at': UTC_NOW,
|
||||
'migration_status': None},
|
||||
db.volume_destroy(self.ctxt, volume['id']))
|
||||
self.assertRaises(exception.VolumeNotFound, db.volume_get,
|
||||
self.ctxt, volume['id'])
|
||||
|
||||
@ -1803,8 +1812,11 @@ class DBAPIQuotaClassTestCase(BaseTest):
|
||||
qc = db.quota_class_get(self.ctxt, 'test_qc', 'test_resource')
|
||||
self._assertEqualObjects(self.sample_qc, qc)
|
||||
|
||||
def test_quota_class_destroy(self):
|
||||
db.quota_class_destroy(self.ctxt, 'test_qc', 'test_resource')
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=UTC_NOW)
|
||||
def test_quota_class_destroy(self, utcnow_mock):
|
||||
self.assertDictEqual(
|
||||
{'deleted': True, 'deleted_at': UTC_NOW},
|
||||
db.quota_class_destroy(self.ctxt, 'test_qc', 'test_resource'))
|
||||
self.assertRaises(exception.QuotaClassNotFound,
|
||||
db.quota_class_get, self.ctxt,
|
||||
'test_qc', 'test_resource')
|
||||
@ -1909,10 +1921,12 @@ class DBAPIQuotaTestCase(BaseTest):
|
||||
'volumes': {'reserved': 1, 'in_use': 0}},
|
||||
quota_usage)
|
||||
|
||||
def test_quota_destroy(self):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=UTC_NOW)
|
||||
def test_quota_destroy(self, utcnow_mock):
|
||||
db.quota_create(self.ctxt, 'project1', 'resource1', 41)
|
||||
self.assertIsNone(db.quota_destroy(self.ctxt, 'project1',
|
||||
'resource1'))
|
||||
self.assertDictEqual(
|
||||
{'deleted': True, 'deleted_at': UTC_NOW},
|
||||
db.quota_destroy(self.ctxt, 'project1', 'resource1'))
|
||||
self.assertRaises(exception.ProjectQuotaNotFound, db.quota_get,
|
||||
self.ctxt, 'project1', 'resource1')
|
||||
|
||||
@ -2134,9 +2148,13 @@ class DBAPIBackupTestCase(BaseTest):
|
||||
self._assertEqualObjects(updated_values, updated_backup,
|
||||
self._ignored_keys)
|
||||
|
||||
def test_backup_destroy(self):
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', return_value=UTC_NOW)
|
||||
def test_backup_destroy(self, utcnow_mock):
|
||||
for backup in self.created:
|
||||
db.backup_destroy(self.ctxt, backup['id'])
|
||||
self.assertDictEqual(
|
||||
{'status': fields.BackupStatus.DELETED, 'deleted': True,
|
||||
'deleted_at': UTC_NOW},
|
||||
db.backup_destroy(self.ctxt, backup['id']))
|
||||
self.assertFalse(db.backup_get_all(self.ctxt))
|
||||
|
||||
def test_backup_not_found(self):
|
||||
|
@ -22,6 +22,7 @@ import six
|
||||
import time
|
||||
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from cinder import context
|
||||
from cinder import db
|
||||
@ -146,7 +147,8 @@ class QoSSpecsTestCase(test.TestCase):
|
||||
return vol_types
|
||||
|
||||
def fake_db_delete(context, id):
|
||||
pass
|
||||
return {'deleted': True,
|
||||
'deleted_at': timeutils.utcnow()}
|
||||
|
||||
def fake_disassociate_all(context, id):
|
||||
pass
|
||||
|
@ -90,9 +90,8 @@ def destroy(context, id):
|
||||
if id is None:
|
||||
msg = _("id cannot be None")
|
||||
raise exception.InvalidVolumeType(reason=msg)
|
||||
else:
|
||||
elevated = context if context.is_admin else context.elevated()
|
||||
db.volume_type_destroy(elevated, id)
|
||||
return db.volume_type_destroy(elevated, id)
|
||||
|
||||
|
||||
def get_all_types(context, inactive=0, filters=None, marker=None,
|
||||
|
Loading…
Reference in New Issue
Block a user