]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Handle OverQuota exception during volume transfer
authorLisaLi <xiaoyan.li@intel.com>
Wed, 17 Feb 2016 05:24:50 +0000 (13:24 +0800)
committerLisaLi <xiaoyan.li@intel.com>
Fri, 19 Feb 2016 05:34:28 +0000 (13:34 +0800)
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

cinder/tests/unit/test_volume_transfer.py
cinder/transfer/api.py

index 4345b50395a11f2349663d22ed882f3f2e2a99dc..6024026b6a3d18084c7cbc64b35cd690a399b11b 100644 (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)
index e59635c9696d197d1d61cb1b110ada4827aec1b5..20b90cdcc28eda372fa6ad435143f919f6bbbfa1 100644 (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}