summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorEoghan Glynn <eglynn@redhat.com>2012-07-04 11:21:19 +0000
committerEoghan Glynn <eglynn@redhat.com>2012-07-04 16:39:04 +0100
commitdea224ae26c752d328ccbb622048a63e990bee50 (patch)
tree0cab8091383831ff520a4bebe121b5044da6a3a0 /nova
parent980c76266629ea66bc23fddb02f5be61c51d873c (diff)
downloadnova-dea224ae26c752d328ccbb622048a63e990bee50.tar.gz
nova-dea224ae26c752d328ccbb622048a63e990bee50.tar.xz
nova-dea224ae26c752d328ccbb622048a63e990bee50.zip
Distinguish over-quota for volume size and number.
Fixes LP 1020634 Ensure that exceeding the allowed number of volumes is not mis-represented in log messages and exception handling as excessive space usage. Change-Id: I71ec995c77bc447bfc9221084b057bd8d69a4513
Diffstat (limited to 'nova')
-rw-r--r--nova/exception.py4
-rw-r--r--nova/tests/test_volume.py33
-rw-r--r--nova/volume/api.py25
3 files changed, 58 insertions, 4 deletions
diff --git a/nova/exception.py b/nova/exception.py
index c1f417afe..ff9a20a41 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -1005,6 +1005,10 @@ class VolumeSizeTooLarge(QuotaError):
message = _("Maximum volume size exceeded")
+class VolumeLimitExceeded(QuotaError):
+ message = _("Maximum number of volumes allowed (%(allowed)d) exceeded")
+
+
class FloatingIpLimitExceeded(QuotaError):
message = _("Maximum number of floating ips exceeded")
diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py
index 2e149f950..0478eb545 100644
--- a/nova/tests/test_volume.py
+++ b/nova/tests/test_volume.py
@@ -121,6 +121,39 @@ class VolumeTestCase(test.TestCase):
self.context,
volume_id)
+ def _do_test_create_over_quota(self, resource, expected):
+ """Test volume creation over quota."""
+
+ def fake_reserve(context, **deltas):
+ kwargs = dict(overs=[resource],
+ quotas=dict(gigabytes=1000, volumes=10),
+ usages=dict(gigabytes=dict(reserved=1, in_use=999),
+ volumes=dict(reserved=1, in_use=9)))
+ raise exception.OverQuota(**kwargs)
+
+ def fake_commit(context, reservations):
+ self.fail('should not commit over quota')
+
+ self.stubs.Set(QUOTAS, 'reserve', fake_reserve)
+ self.stubs.Set(QUOTAS, 'commit', fake_commit)
+
+ volume_api = nova.volume.api.API()
+
+ self.assertRaises(expected,
+ volume_api.create,
+ self.context,
+ 2,
+ 'name',
+ 'description')
+
+ def test_create_volumes_over_quota(self):
+ self._do_test_create_over_quota('volumes',
+ exception.VolumeLimitExceeded)
+
+ def test_create_gigabytes_over_quota(self):
+ self._do_test_create_over_quota('gigabytes',
+ exception.VolumeSizeTooLarge)
+
def test_delete_busy_volume(self):
"""Test volume survives deletion if driver reports it as busy."""
volume = self._create_volume()
diff --git a/nova/volume/api.py b/nova/volume/api.py
index 28f78a7e1..ee079021a 100644
--- a/nova/volume/api.py
+++ b/nova/volume/api.py
@@ -82,11 +82,28 @@ class API(base.Base):
try:
reservations = QUOTAS.reserve(context, volumes=1, gigabytes=size)
- except exception.OverQuota:
+ except exception.OverQuota as e:
+ overs = e.kwargs['overs']
+ usages = e.kwargs['usages']
+ quotas = e.kwargs['quotas']
+
+ def _consumed(name):
+ return (usages[name]['reserved'] + usages[name]['in_use'])
+
pid = context.project_id
- LOG.warn(_("Quota exceeded for %(pid)s, tried to create"
- " %(size)sG volume") % locals())
- raise exception.VolumeSizeTooLarge()
+ if 'gigabytes' in overs:
+ consumed = _consumed('gigabytes')
+ quota = quotas['gigabytes']
+ LOG.warn(_("Quota exceeded for %(pid)s, tried to create "
+ "%(size)sG volume (%(consumed)dG of %(quota)dG "
+ "already consumed)") % locals())
+ raise exception.VolumeSizeTooLarge()
+ elif 'volumes' in overs:
+ consumed = _consumed('volumes')
+ LOG.warn(_("Quota exceeded for %(pid)s, tried to create "
+ "volume (%(consumed)d volumes already consumed)")
+ % locals())
+ raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])
if availability_zone is None:
availability_zone = FLAGS.storage_availability_zone