Making reservations before group creation

The problem here was when we do reservation after creating group,
synchronization during quota_reserve() gets in_use value as 1 as
the group has already been created befre reserving & quota commit
updates groups in_use value as +1, hence making 2 for the first
time. So, reservations have been made before creating groups.

Change-Id: If5f3cf75e39ed932028be7a2fb583c2576cb04bf
Closes-Bug: 1711381
This commit is contained in:
Abhishek Sharma 2017-08-20 17:33:47 -05:00
parent 772770327a
commit fc99c3cfdd
3 changed files with 39 additions and 11 deletions

View File

@ -153,6 +153,13 @@ class API(base.Base):
'volume_type_ids': [t['id'] for t in req_volume_types],
'group_type_id': req_group_type['id'],
'replication_status': c_fields.ReplicationStatus.DISABLED}
try:
reservations = GROUP_QUOTAS.reserve(context,
project_id=context.project_id,
groups=1)
except exception.OverQuota as e:
quota_utils.process_reserve_over_quota(context, e,
resource='groups')
group = None
try:
group = objects.Group(context=context, **kwargs)
@ -161,6 +168,7 @@ class API(base.Base):
with excutils.save_and_reraise_exception():
LOG.error("Error occurred when creating group"
" %s.", name)
GROUP_QUOTAS.rollback(context, reservations)
request_spec_list = []
filter_properties_list = []
@ -176,7 +184,7 @@ class API(base.Base):
group_filter_properties = {}
# Update quota for groups
self.update_quota(context, group, 1)
GROUP_QUOTAS.commit(context, reservations)
self._cast_create_group(context, group,
group_spec,
@ -215,7 +223,13 @@ class API(base.Base):
'volume_type_ids': volume_type_ids,
'replication_status': c_fields.ReplicationStatus.DISABLED
}
try:
reservations = GROUP_QUOTAS.reserve(context,
project_id=context.project_id,
groups=1)
except exception.OverQuota as e:
quota_utils.process_reserve_over_quota(context, e,
resource='groups')
group = None
try:
group = objects.Group(context=context, **kwargs)
@ -226,19 +240,22 @@ class API(base.Base):
LOG.error("Source Group %(source_group)s not found when "
"creating group %(group)s from source.",
{'group': name, 'source_group': source_group_id})
GROUP_QUOTAS.rollback(context, reservations)
except exception.GroupSnapshotNotFound:
with excutils.save_and_reraise_exception():
LOG.error("Group snapshot %(group_snap)s not found when "
"creating group %(group)s from source.",
{'group': name, 'group_snap': group_snapshot_id})
GROUP_QUOTAS.rollback(context, reservations)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error("Error occurred when creating group"
" %(group)s from group_snapshot %(grp_snap)s.",
{'group': name, 'grp_snap': group_snapshot_id})
GROUP_QUOTAS.rollback(context, reservations)
# Update quota for groups
self.update_quota(context, group, 1)
GROUP_QUOTAS.commit(context, reservations)
if not group.host:
msg = _("No host to create group %s.") % group.id

View File

@ -591,7 +591,11 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
self.assertEqual(fields.ConsistencyGroupStatus.DELETED, cg.status)
self.assertIsNone(cg.host)
def test_create_delete_consistencygroup_update_quota(self):
@mock.patch('cinder.quota.GROUP_QUOTAS.reserve',
return_value='reservations')
@mock.patch('cinder.quota.GROUP_QUOTAS.commit')
def test_create_delete_consistencygroup_update_quota(self, mock_commit,
mock_reserve):
name = 'mycg'
description = 'consistency group 1'
fake_grp_type = {'id': fake.GROUP_TYPE_ID, 'name': 'fake_grp_type'}
@ -604,12 +608,14 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
self.mock_object(self.cg_api, 'update_quota')
cg = self.cg_api.create(self.ctxt, name, description,
fake.GROUP_TYPE_ID, fake_vol_type['name'])
self.cg_api.update_quota.assert_called_once_with(
self.ctxt, cg, 1)
# Verify the quota reservation and commit was called
mock_reserve.assert_called_once_with(self.ctxt,
project_id=self.ctxt.project_id,
groups=1)
mock_commit.assert_called_once_with(self.ctxt, 'reservations')
self.assertEqual(fields.ConsistencyGroupStatus.CREATING, cg.status)
self.assertIsNone(cg.host)
self.cg_api.update_quota.reset_mock()
cg.status = fields.ConsistencyGroupStatus.ERROR
self.cg_api.delete(self.ctxt, cg)

View File

@ -577,7 +577,10 @@ class GroupsAPITestCase(test.TestCase):
self.assertEqual(fields.GroupStatus.DELETED, group.status)
self.assertIsNone(group.host)
def test_create_delete_group_update_quota(self):
@mock.patch('cinder.quota.GROUP_QUOTAS.reserve',
return_value='reservations')
@mock.patch('cinder.quota.GROUP_QUOTAS.commit')
def test_create_delete_group_update_quota(self, mock_commit, mock_reserve):
name = 'mygroup'
description = 'group 1'
grp_type = {'id': fake.GROUP_TYPE_ID, 'name': 'group_type'}
@ -589,12 +592,14 @@ class GroupsAPITestCase(test.TestCase):
self.mock_object(self.group_api, 'update_quota')
group = self.group_api.create(self.ctxt, name, description,
grp_type['id'], [fake_type['id']])
self.group_api.update_quota.assert_called_once_with(
self.ctxt, group, 1)
# Verify that quota reservation and commit was called
mock_reserve.assert_called_once_with(self.ctxt,
project_id=self.ctxt.project_id,
groups=1)
mock_commit.assert_called_once_with(self.ctxt, 'reservations')
self.assertEqual(fields.GroupStatus.CREATING, group.status)
self.assertIsNone(group.host)
self.group_api.update_quota.reset_mock()
group.status = fields.GroupStatus.ERROR
self.group_api.delete(self.ctxt, group)