]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add snapshots to the volume usage audit report
authorMichael Kerrin <michael.kerrin@hp.com>
Tue, 19 Mar 2013 18:04:39 +0000 (18:04 +0000)
committerMichael Kerrin <michael.kerrin@hp.com>
Tue, 19 Mar 2013 18:19:45 +0000 (18:19 +0000)
* Added tests for db api call volume_get_active_by_window called by the volume
usage audit report.

* Added new db api called snapshot_get_active_by_window & test it. This is
similar to the volume_get_active_by_window method but returns the snapshots
 active the supplied time window.

* Integrate the above into the cinder-volume-usage-audit script to report on
  all the active snapshots as well as volumes in the specified time frame.

Fixes: bug #1157110
Change-Id: I7597da20c62150a8f6c74cbfeec159f68064d2a6

bin/cinder-volume-usage-audit
cinder/db/api.py
cinder/db/sqlalchemy/api.py
cinder/tests/test_volume.py
cinder/volume/utils.py

index 96660839ea1b092adae6a1dd0bde62afd99838b4..053de79a13d4c13c5d4359cc52670985a6aa5d37 100755 (executable)
@@ -67,6 +67,12 @@ if __name__ == '__main__':
     print _("Starting volume usage audit")
     msg = _("Creating usages for %(begin_period)s until %(end_period)s")
     print (msg % {"begin_period": str(begin), "end_period": str(end)})
+
+    extra_info = {
+        'audit_period_beginning': str(begin),
+        'audit_period_ending': str(end),
+    }
+
     volumes = db.volume_get_active_by_window(admin_context,
                                              begin,
                                              end)
@@ -77,4 +83,18 @@ if __name__ == '__main__':
                     admin_context, volume_ref)
         except Exception, e:
             print traceback.format_exc(e)
+
+    snapshots = db.snapshot_get_active_by_window(admin_context,
+                                                 begin,
+                                                 end)
+    print _("Found %d snapshots") % len(snapshots)
+    for snapshot_ref in snapshots:
+        try:
+            cinder.volume.utils.notify_about_snapshot_usage(admin_context,
+                                                            snapshot_ref,
+                                                            'exists',
+                                                            extra_info)
+        except Exception, e:
+            print traceback.fromat_exc(e)
+
     print _("Volume usage audit completed")
index 4f3b92544ab9edf57ad76419d7760e8857aa0fac..dc5e675da5fda90ebe5473d632d63822921fd401 100644 (file)
@@ -317,6 +317,13 @@ def snapshot_data_get_for_project(context, project_id, session=None):
                                               session=None)
 
 
+def snapshot_get_active_by_window(context, begin, end=None, project_id=None):
+    """Get all the snapshots inside the window.
+
+    Specifying a project_id will filter for a certain project."""
+    return IMPL.snapshot_get_active_by_window(context, begin, end, project_id)
+
+
 ####################
 
 
index 67a4e1e7f6c35ff42c9c26cf0a261d29b88da86a..68b9671eb0670d6b4f9bf8830dbfe280691cfa31 100644 (file)
@@ -1260,6 +1260,22 @@ def snapshot_data_get_for_project(context, project_id, session=None):
     return (result[0] or 0, result[1] or 0)
 
 
+@require_context
+def snapshot_get_active_by_window(context, begin, end=None, project_id=None):
+    """Return snapshots that were active during window."""
+    session = get_session()
+    query = session.query(models.Snapshot)
+
+    query = query.filter(or_(models.Snapshot.deleted_at == None,
+                             models.Snapshot.deleted_at > begin))
+    if end:
+        query = query.filter(models.Snapshot.created_at < end)
+    if project_id:
+        query = query.filter_by(project_id=project_id)
+
+    return query.all()
+
+
 @require_context
 def snapshot_update(context, snapshot_id, values):
     session = get_session()
index 95ae9cf33adb0aea1e7bad64ea5fe7cb4f5eb242..278e10584f76c2d51ccb1951167d7086b4d9bb6a 100644 (file)
@@ -857,6 +857,159 @@ class VolumeTestCase(test.TestCase):
         snap = db.snapshot_get(context.get_admin_context(), snapshot['id'])
         self.assertEquals(snap['display_name'], 'test update name')
 
+    def test_volume_get_active_by_window(self):
+        # Find all all volumes valid within a timeframe window.
+        try:  # Not in window
+            db.volume_create(
+                self.context,
+                {
+                    'id': 1,
+                    'host': 'devstack',
+                    'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+                    'deleted': True, 'status': 'deleted',
+                    'deleted_at': datetime.datetime(1, 2, 1, 1, 1, 1),
+                }
+            )
+        except exception.VolumeNotFound:
+            pass
+
+        try:  # In - deleted in window
+            db.volume_create(
+                self.context,
+                {
+                    'id': 2,
+                    'host': 'devstack',
+                    'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+                    'deleted': True, 'status': 'deleted',
+                    'deleted_at': datetime.datetime(1, 3, 10, 1, 1, 1),
+                }
+            )
+        except exception.VolumeNotFound:
+            pass
+
+        try:  # In - deleted after window
+            db.volume_create(
+                self.context,
+                {
+                    'id': 3,
+                    'host': 'devstack',
+                    'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+                    'deleted': True, 'status': 'deleted',
+                    'deleted_at': datetime.datetime(1, 5, 1, 1, 1, 1),
+                }
+            )
+        except exception.VolumeNotFound:
+            pass
+
+        # In - created in window
+        db.volume_create(
+            self.context,
+            {
+                'id': 4,
+                'host': 'devstack',
+                'created_at': datetime.datetime(1, 3, 10, 1, 1, 1),
+            }
+        )
+
+        # Not of window.
+        db.volume_create(
+            self.context,
+            {
+                'id': 5,
+                'host': 'devstack',
+                'created_at': datetime.datetime(1, 5, 1, 1, 1, 1),
+            }
+        )
+
+        volumes = db.volume_get_active_by_window(
+            self.context,
+            datetime.datetime(1, 3, 1, 1, 1, 1),
+            datetime.datetime(1, 4, 1, 1, 1, 1))
+        self.assertEqual(len(volumes), 3)
+        self.assertEqual(volumes[0].id, u'2')
+        self.assertEqual(volumes[1].id, u'3')
+        self.assertEqual(volumes[2].id, u'4')
+
+    def test_snapshot_get_active_by_window(self):
+        # Find all all snapshots valid within a timeframe window.
+        vol = db.volume_create(self.context, {'id': 1})
+
+        try:  # Not in window
+            db.snapshot_create(
+                self.context,
+                {
+                    'id': 1,
+                    'host': 'devstack',
+                    'volume_id': 1,
+                    'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+                    'deleted': True, 'status': 'deleted',
+                    'deleted_at': datetime.datetime(1, 2, 1, 1, 1, 1),
+                }
+            )
+        except exception.SnapshotNotFound:
+            pass
+
+        try:  # In - deleted in window
+            db.snapshot_create(
+                self.context,
+                {
+                    'id': 2,
+                    'host': 'devstack',
+                    'volume_id': 1,
+                    'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+                    'deleted': True, 'status': 'deleted',
+                    'deleted_at': datetime.datetime(1, 3, 10, 1, 1, 1),
+                }
+            )
+        except exception.SnapshotNotFound:
+            pass
+
+        try:  # In - deleted after window
+            db.snapshot_create(
+                self.context,
+                {
+                    'id': 3,
+                    'host': 'devstack',
+                    'volume_id': 1,
+                    'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+                    'deleted': True, 'status': 'deleted',
+                    'deleted_at': datetime.datetime(1, 5, 1, 1, 1, 1),
+                }
+            )
+        except exception.SnapshotNotFound:
+            pass
+
+        # In - created in window
+        db.snapshot_create(
+            self.context,
+            {
+                'id': 4,
+                'host': 'devstack',
+                'volume_id': 1,
+                'created_at': datetime.datetime(1, 3, 10, 1, 1, 1),
+            }
+        )
+
+        # Not of window.
+        db.snapshot_create(
+            self.context,
+            {
+                'id': 5,
+                'host': 'devstack',
+                'volume_id': 1,
+                'created_at': datetime.datetime(1, 5, 1, 1, 1, 1),
+            }
+        )
+
+        snapshots = db.snapshot_get_active_by_window(
+            self.context,
+            datetime.datetime(1, 3, 1, 1, 1, 1),
+            datetime.datetime(1, 4, 1, 1, 1, 1))
+        self.assertEqual(len(snapshots), 3)
+        self.assertEqual(snapshots[0].id, u'2')
+        self.assertEqual(snapshots[1].id, u'3')
+        self.assertEqual(snapshots[2].id, u'4')
+
 
 class DriverTestCase(test.TestCase):
     """Base Test class for Drivers."""
index 5d53219bf1c519b4f4be42eb5549146c7394dd66..b7f7b35468311f52eb3beb6f2a6d9aba5e5a40a9 100644 (file)
@@ -54,10 +54,11 @@ def notify_usage_exists(context, volume_ref, current_period=False):
                               'exists', extra_usage_info=extra_usage_info)
 
 
-def _usage_from_volume(context, volume_ref, **kw):
-    def null_safe_str(s):
-        return str(s) if s else ''
+def null_safe_str(s):
+    return str(s) if s else ''
+
 
+def _usage_from_volume(context, volume_ref, **kw):
     usage_info = dict(tenant_id=volume_ref['project_id'],
                       user_id=volume_ref['user_id'],
                       volume_id=volume_ref['id'],
@@ -86,3 +87,35 @@ def notify_about_volume_usage(context, volume, event_suffix,
     notifier_api.notify(context, 'volume.%s' % host,
                         'volume.%s' % event_suffix,
                         notifier_api.INFO, usage_info)
+
+
+def _usage_from_snapshot(context, snapshot_ref, **extra_usage_info):
+    usage_info = {
+        'tenant_id': snapshot_ref['project_id'],
+        'user_id': snapshot_ref['user_id'],
+        'volume_id': snapshot_ref['volume_id'],
+        'volume_size': snapshot_ref['volume_size'],
+        'snapshot_id': snapshot_ref['id'],
+        'display_name': snapshot_ref['display_name'],
+        'created_at': str(snapshot_ref['created_at']),
+        'status': snapshot_ref['status'],
+        'deleted': null_safe_str(snapshot_ref['deleted'])
+    }
+
+    usage_info.update(extra_usage_info)
+    return usage_info
+
+
+def notify_about_snapshot_usage(context, snapshot, event_suffix,
+                                extra_usage_info=None, host=None):
+    if not host:
+        host = FLAGS.host
+
+    if not extra_usage_info:
+        extra_usage_info = {}
+
+    usage_info = _usage_from_snapshot(context, snapshot, **extra_usage_info)
+
+    notifier_api.notify(context, 'snapshot.%s' % host,
+                        'snapshot.%s' % event_suffix,
+                        notifier_api.INFO, usage_info)