Merge "Add quota limit check and enhance roll back for cg create"
This commit is contained in:
commit
49040c13ab
cinder
@ -45,6 +45,7 @@ CONF = cfg.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CGQUOTAS = quota.CGQUOTAS
|
||||
QUOTAS = quota.QUOTAS
|
||||
VALID_REMOVE_VOL_FROM_CG_STATUS = (
|
||||
'available',
|
||||
'in-use',
|
||||
@ -231,6 +232,16 @@ class API(base.Base):
|
||||
"will be created.")
|
||||
raise exception.InvalidConsistencyGroup(reason=msg)
|
||||
|
||||
try:
|
||||
values = {'volumes': len(snapshots)}
|
||||
QUOTAS.limit_check(context, project_id=context.project_id,
|
||||
**values)
|
||||
except exception.OverQuota as e:
|
||||
group.destroy()
|
||||
quotas = e.kwargs['quotas']
|
||||
raise exception.VolumeLimitExceeded(
|
||||
allowed=e.kwargs['overs'], limit=quotas['volumes'])
|
||||
|
||||
for snapshot in snapshots:
|
||||
kwargs = {}
|
||||
kwargs['availability_zone'] = group.availability_zone
|
||||
@ -265,6 +276,10 @@ class API(base.Base):
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
try:
|
||||
new_vols = self.db.volume_get_all_by_group(context,
|
||||
group.id)
|
||||
for vol in new_vols:
|
||||
self.volume_api.delete(context, vol, force=True)
|
||||
group.destroy()
|
||||
finally:
|
||||
LOG.error("Error occurred when creating consistency "
|
||||
@ -295,6 +310,16 @@ class API(base.Base):
|
||||
"will be created.")
|
||||
raise exception.InvalidConsistencyGroup(reason=msg)
|
||||
|
||||
try:
|
||||
values = {'volumes': len(source_vols)}
|
||||
QUOTAS.limit_check(context, project_id=context.project_id,
|
||||
**values)
|
||||
except exception.OverQuota as e:
|
||||
group.destroy()
|
||||
quotas = e.kwargs['quotas']
|
||||
raise exception.VolumeLimitExceeded(
|
||||
allowed=e.kwargs['overs'], limit=quotas['volumes'])
|
||||
|
||||
for source_vol in source_vols:
|
||||
kwargs = {}
|
||||
kwargs['availability_zone'] = group.availability_zone
|
||||
@ -329,6 +354,10 @@ class API(base.Base):
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
try:
|
||||
new_vols = self.db.volume_get_all_by_group(context,
|
||||
group.id)
|
||||
for vol in new_vols:
|
||||
self.volume_api.delete(context, vol, force=True)
|
||||
group.destroy()
|
||||
finally:
|
||||
LOG.error("Error occurred when creating consistency "
|
||||
|
@ -1133,9 +1133,10 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
|
||||
consistencygroup.destroy()
|
||||
|
||||
@mock.patch('cinder.quota.QuotaEngine.limit_check')
|
||||
@mock.patch(
|
||||
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
|
||||
def test_create_consistencygroup_from_src(self, mock_validate):
|
||||
def test_create_consistencygroup_from_src(self, mock_validate, mock_quota):
|
||||
self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create)
|
||||
|
||||
consistencygroup = utils.create_consistencygroup(self.ctxt)
|
||||
@ -1178,7 +1179,8 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
consistencygroup.destroy()
|
||||
cgsnapshot.destroy()
|
||||
|
||||
def test_create_consistencygroup_from_src_cg(self):
|
||||
@mock.patch('cinder.quota.QuotaEngine.limit_check')
|
||||
def test_create_consistencygroup_from_src_cg(self, mock_quota):
|
||||
self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create)
|
||||
|
||||
source_cg = utils.create_consistencygroup(self.ctxt)
|
||||
@ -1434,11 +1436,12 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
self.assertEqual(404, res_dict['itemNotFound']['code'])
|
||||
self.assertIsNotNone(res_dict['itemNotFound']['message'])
|
||||
|
||||
@mock.patch('cinder.quota.QuotaEngine.limit_check')
|
||||
@mock.patch.object(volume_api.API, 'create',
|
||||
side_effect=exception.CinderException(
|
||||
'Create volume failed.'))
|
||||
def test_create_consistencygroup_from_src_cgsnapshot_create_volume_failed(
|
||||
self, mock_create):
|
||||
self, mock_create, mock_quota):
|
||||
consistencygroup = utils.create_consistencygroup(self.ctxt)
|
||||
volume_id = utils.create_volume(
|
||||
self.ctxt,
|
||||
@ -1475,11 +1478,12 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
consistencygroup.destroy()
|
||||
cgsnapshot.destroy()
|
||||
|
||||
@mock.patch('cinder.quota.QuotaEngine.limit_check')
|
||||
@mock.patch.object(volume_api.API, 'create',
|
||||
side_effect=exception.CinderException(
|
||||
'Create volume failed.'))
|
||||
def test_create_consistencygroup_from_src_cg_create_volume_failed(
|
||||
self, mock_create):
|
||||
self, mock_create, mock_quota):
|
||||
source_cg = utils.create_consistencygroup(self.ctxt)
|
||||
volume_id = utils.create_volume(
|
||||
self.ctxt,
|
||||
@ -1505,3 +1509,88 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
|
||||
db.volume_destroy(self.ctxt.elevated(), volume_id)
|
||||
source_cg.destroy()
|
||||
|
||||
@mock.patch('cinder.quota.QuotaEngine.limit_check')
|
||||
def test_create_consistencygroup_from_src_cg_over_quota(self, mock_quota):
|
||||
self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create)
|
||||
|
||||
source_cg = utils.create_consistencygroup(self.ctxt)
|
||||
volume_id = utils.create_volume(
|
||||
self.ctxt,
|
||||
consistencygroup_id=source_cg.id)['id']
|
||||
|
||||
mock_quota.side_effect = exception.OverQuota(
|
||||
overs=10, quotas='volumes', usages={})
|
||||
|
||||
test_cg_name = 'test cg'
|
||||
body = {"consistencygroup-from-src": {"name": test_cg_name,
|
||||
"description":
|
||||
"Consistency Group 1",
|
||||
"source_cgid": source_cg.id}}
|
||||
req = webob.Request.blank('/v2/%s/consistencygroups/create_from_src' %
|
||||
fake.PROJECT_ID)
|
||||
req.method = 'POST'
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
res = req.get_response(fakes.wsgi_app(
|
||||
fake_auth_context=self.user_ctxt))
|
||||
res_dict = jsonutils.loads(res.body)
|
||||
|
||||
self.assertEqual(400, res.status_int)
|
||||
self.assertIn('message', res_dict['badRequest'])
|
||||
|
||||
cg = objects.ConsistencyGroupList.get_all(self.ctxt)
|
||||
# The new cg has been deleted already.
|
||||
self.assertEqual(1, len(cg))
|
||||
|
||||
db.volume_destroy(self.ctxt.elevated(), volume_id)
|
||||
source_cg.destroy()
|
||||
|
||||
@mock.patch('cinder.quota.QuotaEngine.limit_check')
|
||||
@mock.patch(
|
||||
'cinder.api.openstack.wsgi.Controller.validate_name_and_description')
|
||||
def test_create_consistencygroup_from_src_cgsnapshot_over_quota(
|
||||
self, mock_validate, mock_quota):
|
||||
self.mock_object(volume_api.API, "create", v2_fakes.fake_volume_create)
|
||||
|
||||
consistencygroup = utils.create_consistencygroup(self.ctxt)
|
||||
volume_id = utils.create_volume(
|
||||
self.ctxt,
|
||||
consistencygroup_id=consistencygroup.id)['id']
|
||||
cgsnapshot = utils.create_cgsnapshot(
|
||||
self.ctxt, consistencygroup_id=consistencygroup.id)
|
||||
snapshot = utils.create_snapshot(
|
||||
self.ctxt,
|
||||
volume_id,
|
||||
cgsnapshot_id=cgsnapshot.id,
|
||||
status=fields.SnapshotStatus.AVAILABLE)
|
||||
|
||||
mock_quota.side_effect = exception.OverQuota(
|
||||
overs=10, quotas='volumes', usages={})
|
||||
|
||||
test_cg_name = 'test cg'
|
||||
body = {"consistencygroup-from-src": {"name": test_cg_name,
|
||||
"description":
|
||||
"Consistency Group 1",
|
||||
"cgsnapshot_id": cgsnapshot.id}}
|
||||
req = webob.Request.blank('/v2/%s/consistencygroups/create_from_src' %
|
||||
fake.PROJECT_ID)
|
||||
req.method = 'POST'
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
res = req.get_response(fakes.wsgi_app(
|
||||
fake_auth_context=self.user_ctxt))
|
||||
res_dict = jsonutils.loads(res.body)
|
||||
|
||||
self.assertEqual(400, res.status_int)
|
||||
self.assertIn('message', res_dict['badRequest'])
|
||||
self.assertTrue(mock_validate.called)
|
||||
|
||||
cg = objects.ConsistencyGroupList.get_all(self.ctxt)
|
||||
# The new cg has been deleted already.
|
||||
self.assertEqual(1, len(cg))
|
||||
|
||||
snapshot.destroy()
|
||||
db.volume_destroy(self.ctxt.elevated(), volume_id)
|
||||
consistencygroup.destroy()
|
||||
cgsnapshot.destroy()
|
||||
|
Loading…
x
Reference in New Issue
Block a user