]> 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)
committerJohn Griffith <john.griffith@solidfire.com>
Tue, 26 Mar 2013 23:48:12 +0000 (17:48 -0600)
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
(cherry picked from commit 1fde5a4fbc73a31453f0fe288a0b4a929d7f3026)

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

index 67a4e1e7f6c35ff42c9c26cf0a261d29b88da86a..ecd0bc689c414594a993ffef88f6151e5c5cfde7 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):