From: LisaLi Date: Wed, 17 Feb 2016 05:24:50 +0000 (+0800) Subject: Handle OverQuota exception during volume transfer X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=b5aef3add5df286821de02a5417f07ac5f1101c4;p=openstack-build%2Fcinder-build.git 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 --- diff --git a/cinder/tests/unit/test_volume_transfer.py b/cinder/tests/unit/test_volume_transfer.py index 4345b5039..6024026b6 100644 --- a/cinder/tests/unit/test_volume_transfer.py +++ b/cinder/tests/unit/test_volume_transfer.py @@ -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) diff --git a/cinder/transfer/api.py b/cinder/transfer/api.py index e59635c96..20b90cdcc 100644 --- a/cinder/transfer/api.py +++ b/cinder/transfer/api.py @@ -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}