]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add the volume and snapshot gigabytes together.
authorCory Stone <corystone@gmail.com>
Mon, 25 Mar 2013 20:09:37 +0000 (15:09 -0500)
committerCory Stone <corystone@gmail.com>
Mon, 25 Mar 2013 20:09:37 +0000 (15:09 -0500)
The quota sync functions were not working correctly for both
snapshots and volumes regarding gigabytes. Each would report
their own count as the total gigabytes.

Now the gigabytes sync is separate from the volume and snapshot
count syncs.

Fixes bug #1160004

Change-Id: Ib1200813acb6055412b3f7f6b63fa9ba2b8fa3be

cinder/db/sqlalchemy/api.py
cinder/quota.py
cinder/tests/test_quota.py

index 68b9671eb0670d6b4f9bf8830dbfe280691cfa31..37e21c6da8fd88b4d68cdefdb1663756efd19239 100644 (file)
@@ -607,7 +607,7 @@ def reservation_get(context, uuid, session=None):
 def reservation_get_all_by_project(context, project_id):
     authorize_project_context(context, project_id)
 
-    rows = model_query(context, models.QuotaUsage, read_deleted="no").\
+    rows = model_query(context, models.Reservation, read_deleted="no").\
         filter_by(project_id=project_id).all()
 
     result = {'project_id': project_id}
index 1a1edc92b670269520e454506d5a96c7f26736f2..d006f1f8121275ea223db9a79c0065c60d03c47f 100644 (file)
@@ -730,17 +730,30 @@ class QuotaEngine(object):
 
 
 def _sync_volumes(context, project_id, session):
-    return dict(zip(('volumes', 'gigabytes'),
-                db.volume_data_get_for_project(context,
-                                               project_id,
-                                               session=session)))
+    (volumes, gigs) = db.volume_data_get_for_project(context,
+                                                     project_id,
+                                                     session=session)
+    return {'volumes': volumes}
 
 
 def _sync_snapshots(context, project_id, session):
-    return dict(zip(('snapshots', 'gigabytes'),
-                db.snapshot_data_get_for_project(context,
-                                                 project_id,
-                                                 session=session)))
+    (snapshots, gigs) = db.snapshot_data_get_for_project(context,
+                                                         project_id,
+                                                         session=session)
+    return {'snapshots': snapshots}
+
+
+def _sync_gigabytes(context, project_id, session):
+    (_junk, vol_gigs) = db.volume_data_get_for_project(context,
+                                                       project_id,
+                                                       session=session)
+    if FLAGS.no_snapshot_gb_quota:
+        return {'gigabytes': vol_gigs}
+
+    (_junk, snap_gigs) = db.snapshot_data_get_for_project(context,
+                                                          project_id,
+                                                          session=session)
+    return {'gigabytes': vol_gigs + snap_gigs}
 
 
 QUOTAS = QuotaEngine()
@@ -749,8 +762,7 @@ QUOTAS = QuotaEngine()
 resources = [
     ReservableResource('volumes', _sync_volumes, 'quota_volumes'),
     ReservableResource('snapshots', _sync_snapshots, 'quota_snapshots'),
-    ReservableResource('gigabytes', _sync_volumes, 'quota_gigabytes'),
-    ReservableResource('gigabytes', _sync_snapshots, 'quota_gigabytes'), ]
+    ReservableResource('gigabytes', _sync_gigabytes, 'quota_gigabytes'), ]
 
 
 QUOTAS.register_resources(resources)
index 20b956335f85cda9ff859c61a1f81068aec20b0b..53370ff01d61cbe0551a487bb2ea89b44739ed07 100644 (file)
@@ -71,6 +71,15 @@ class QuotaIntegrationTestCase(test.TestCase):
         vol['status'] = 'available'
         return db.volume_create(self.context, vol)
 
+    def _create_snapshot(self, volume):
+        snapshot = {}
+        snapshot['user_id'] = self.user_id
+        snapshot['project_id'] = self.project_id
+        snapshot['volume_id'] = volume['id']
+        snapshot['volume_size'] = volume['size']
+        snapshot['status'] = 'available'
+        return db.snapshot_create(self.context, snapshot)
+
     def test_too_many_volumes(self):
         volume_ids = []
         for i in range(FLAGS.quota_volumes):
@@ -92,6 +101,47 @@ class QuotaIntegrationTestCase(test.TestCase):
         for volume_id in volume_ids:
             db.volume_destroy(self.context, volume_id)
 
+    def test_too_many_combined_gigabytes(self):
+        vol_ref = self._create_volume(size=10)
+        snap_ref = self._create_snapshot(vol_ref)
+        self.assertRaises(exception.QuotaError,
+                          volume.API().create_snapshot,
+                          self.context, vol_ref, '', '')
+        usages = db.quota_usage_get_all_by_project(self.context,
+                                                   self.project_id)
+        self.assertEqual(usages['gigabytes']['in_use'], 20)
+        db.snapshot_destroy(self.context, snap_ref['id'])
+        db.volume_destroy(self.context, vol_ref['id'])
+
+    def test_no_snapshot_gb_quota_flag(self):
+        self.flags(quota_volumes=2,
+                   quota_snapshots=2,
+                   quota_gigabytes=20,
+                   no_snapshot_gb_quota=True)
+        vol_ref = self._create_volume(size=10)
+        snap_ref = self._create_snapshot(vol_ref)
+        snap_ref2 = volume.API().create_snapshot(self.context,
+                                                 vol_ref, '', '')
+
+        # Make sure no reservation was created for snapshot gigabytes.
+        reservations = db.reservation_get_all_by_project(self.context,
+                                                         self.project_id)
+        self.assertEqual(reservations.get('gigabytes'), None)
+
+        # Make sure the snapshot volume_size isn't included in usage.
+        vol_type = db.volume_type_create(self.context,
+                                         dict(name=FLAGS.default_volume_type))
+        vol_ref2 = volume.API().create(self.context, 10, '', '')
+        usages = db.quota_usage_get_all_by_project(self.context,
+                                                   self.project_id)
+        self.assertEqual(usages['gigabytes']['in_use'], 20)
+
+        db.snapshot_destroy(self.context, snap_ref['id'])
+        db.snapshot_destroy(self.context, snap_ref2['id'])
+        db.volume_destroy(self.context, vol_ref['id'])
+        db.volume_destroy(self.context, vol_ref2['id'])
+        db.volume_type_destroy(self.context, vol_type['id'])
+
 
 class FakeContext(object):
     def __init__(self, project_id, quota_class):