Handle OverQuota exception during volume transfer

Cinder doesn't correctly handle OverQuota during volume
transfer. It only checks quota volumes and gigabytes,
and ignores quotas in volume type. As a result, when it
exceeds volumes and gigabytes of a volume type, Cinder doesn't
raise exception and allows accept move on.

This patch is to check every over quota in overs and fixes the
problem.

Change-Id: I02ef576ecb3052724bc14a3bd2df842bec554e0d
Closes-bug: #1539459
This commit is contained in:
LisaLi 2016-02-17 13:24:50 +08:00
parent b77835b23a
commit b5aef3add5
2 changed files with 52 additions and 19 deletions

View File

@ -178,6 +178,36 @@ class VolumeTransferTestCase(test.TestCase):
mock.call(mock.ANY, project_id='project_id', **release_opt)]
mock_quota_reserve.assert_has_calls(calls)
@mock.patch.object(QUOTAS, "reserve")
@mock.patch.object(QUOTAS, "add_volume_type_opts")
@mock.patch('cinder.volume.utils.notify_about_volume_usage')
def test_transfer_accept_over_quota(self, mock_notify, mock_quota_voltype,
mock_quota_reserve):
svc = self.start_service('volume', host='test_host')
self.addCleanup(svc.stop)
tx_api = transfer_api.API()
volume = utils.create_volume(self.ctxt, volume_type_id='12345',
updated_at=self.updated_at)
transfer = tx_api.create(self.ctxt, volume.id, 'Description')
fake_overs = ['volumes_lvmdriver-3']
fake_quotas = {'gigabytes_lvmdriver-3': 1,
'volumes_lvmdriver-3': 10}
fake_usages = {'gigabytes_lvmdriver-3': {'reserved': 0, 'in_use': 1},
'volumes_lvmdriver-3': {'reserved': 0, 'in_use': 1}}
mock_quota_reserve.side_effect = exception.OverQuota(
overs=fake_overs,
quotas=fake_quotas,
usages=fake_usages)
self.ctxt.user_id = 'new_user_id'
self.ctxt.project_id = 'new_project_id'
self.assertRaises(exception.VolumeLimitExceeded,
tx_api.accept,
self.ctxt,
transfer['id'],
transfer['auth_key'])
def test_transfer_get(self):
tx_api = transfer_api.API()
volume = utils.create_volume(self.ctxt, updated_at=self.updated_at)

View File

@ -184,25 +184,28 @@ class API(base.Base):
def _consumed(name):
return (usages[name]['reserved'] + usages[name]['in_use'])
if 'gigabytes' in overs:
msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
"%(s_size)sG volume (%(d_consumed)dG of "
"%(d_quota)dG already consumed)")
LOG.warning(msg, {'s_pid': context.project_id,
's_size': vol_ref['size'],
'd_consumed': _consumed('gigabytes'),
'd_quota': quotas['gigabytes']})
raise exception.VolumeSizeExceedsAvailableQuota(
requested=vol_ref['size'],
consumed=_consumed('gigabytes'),
quota=quotas['gigabytes'])
elif 'volumes' in overs:
msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
"volume (%(d_consumed)d volumes "
"already consumed)")
LOG.warning(msg, {'s_pid': context.project_id,
'd_consumed': _consumed('volumes')})
raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])
for over in overs:
if 'gigabytes' in over:
msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
"%(s_size)sG volume (%(d_consumed)dG of "
"%(d_quota)dG already consumed)")
LOG.warning(msg, {'s_pid': context.project_id,
's_size': vol_ref['size'],
'd_consumed': _consumed(over),
'd_quota': quotas[over]})
raise exception.VolumeSizeExceedsAvailableQuota(
requested=vol_ref['size'],
consumed=_consumed(over),
quota=quotas[over])
elif 'volumes' in over:
msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
"volume (%(d_consumed)d volumes "
"already consumed)")
LOG.warning(msg, {'s_pid': context.project_id,
'd_consumed': _consumed(over)})
raise exception.VolumeLimitExceeded(allowed=quotas[over],
name=over)
try:
donor_id = vol_ref['project_id']
reserve_opts = {'volumes': -1, 'gigabytes': -vol_ref.size}