]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Notification with volume and snapshot metadata
authorwanghao <wanghao749@huawei.com>
Wed, 6 May 2015 04:08:00 +0000 (12:08 +0800)
committerwanghao <wanghao749@huawei.com>
Sat, 30 May 2015 01:14:27 +0000 (09:14 +0800)
Now notify message to ceilometer do not contain volume
metadata/glance_metadata and snapshot metadata, which are
useful to bill and enrich resource information in ceilometer.

This feature will add the metadata/glance_metadata of volume
and metadata of snapshot to notification usage info.

Change-Id: I04097be9f2da1d6bc45a2d5770bcd543a3f41887
Implements: blueprint notification-with-volume-and-snapshot-metadata

cinder/tests/unit/test_volume.py
cinder/tests/unit/test_volume_utils.py
cinder/volume/utils.py

index 5b4a6a8556574a2205fa409eda608e65c74bfa3a..b197b088e594da160ad3285e1b268e86243e9417 100644 (file)
@@ -525,6 +525,7 @@ class VolumeTestCase(BaseVolumeTestCase):
             'replication_status': 'disabled',
             'replication_extended_status': None,
             'replication_driver_data': None,
+            'metadata': [],
         }
         self.assertDictMatch(expected, msg['payload'])
         msg = fake_notifier.NOTIFICATIONS[1]
@@ -2823,7 +2824,8 @@ class VolumeTestCase(BaseVolumeTestCase):
             'user_id': 'fake',
             'volume_id': volume['id'],
             'volume_size': 1,
-            'availability_zone': 'nova'
+            'availability_zone': 'nova',
+            'metadata': '',
         }
         self.assertDictMatch(expected, msg['payload'])
         msg = fake_notifier.NOTIFICATIONS[3]
index d97ce9961eef137debf7b9abf98f422d0dd5f846..604b5387bc92f91747aa2e6ae2726c4fd193c622 100644 (file)
 
 """Tests For miscellaneous util methods used with volume."""
 
+
+import datetime
 import mock
+
 from oslo_concurrency import processutils
 from oslo_config import cfg
 from oslo_log import log as logging
@@ -42,7 +45,8 @@ class NotifyUsageTestCase(test.TestCase):
                                                         mock.sentinel.volume,
                                                         'test_suffix')
         self.assertIsNone(output)
-        mock_usage.assert_called_once_with(mock.sentinel.volume)
+        mock_usage.assert_called_once_with(mock.sentinel.context,
+                                           mock.sentinel.volume)
         mock_rpc.get_notifier.assert_called_once_with('volume', 'host1')
         mock_rpc.get_notifier.return_value.info.assert_called_once_with(
             mock.sentinel.context,
@@ -62,7 +66,8 @@ class NotifyUsageTestCase(test.TestCase):
             extra_usage_info={'a': 'b', 'c': 'd'},
             host='host2')
         self.assertIsNone(output)
-        mock_usage.assert_called_once_with(mock.sentinel.volume, a='b', c='d')
+        mock_usage.assert_called_once_with(mock.sentinel.context,
+                                           mock.sentinel.volume, a='b', c='d')
         mock_rpc.get_notifier.assert_called_once_with('volume', 'host2')
         mock_rpc.get_notifier.return_value.info.assert_called_once_with(
             mock.sentinel.context,
@@ -80,7 +85,8 @@ class NotifyUsageTestCase(test.TestCase):
             mock.sentinel.volume,
             'test_suffix')
         self.assertIsNone(output)
-        mock_usage.assert_called_once_with(mock.sentinel.volume)
+        mock_usage.assert_called_once_with(mock.sentinel.context,
+                                           mock.sentinel.volume)
         mock_rpc.get_notifier.assert_called_once_with('replication', 'host1')
         mock_rpc.get_notifier.return_value.info.assert_called_once_with(
             mock.sentinel.context,
@@ -100,7 +106,8 @@ class NotifyUsageTestCase(test.TestCase):
             extra_usage_info={'a': 'b', 'c': 'd'},
             host='host2')
         self.assertIsNone(output)
-        mock_usage.assert_called_once_with(mock.sentinel.volume,
+        mock_usage.assert_called_once_with(mock.sentinel.context,
+                                           mock.sentinel.volume,
                                            a='b', c='d')
         mock_rpc.get_notifier.assert_called_once_with('replication', 'host2')
         mock_rpc.get_notifier.return_value.info.assert_called_once_with(
@@ -119,7 +126,8 @@ class NotifyUsageTestCase(test.TestCase):
             mock.sentinel.volume,
             'test_suffix')
         self.assertIsNone(output)
-        mock_usage.assert_called_once_with(mock.sentinel.volume)
+        mock_usage.assert_called_once_with(mock.sentinel.context,
+                                           mock.sentinel.volume)
         mock_rpc.get_notifier.assert_called_once_with('replication', 'host1')
         mock_rpc.get_notifier.return_value.error.assert_called_once_with(
             mock.sentinel.context,
@@ -139,7 +147,8 @@ class NotifyUsageTestCase(test.TestCase):
             extra_error_info={'a': 'b', 'c': 'd'},
             host='host2')
         self.assertIsNone(output)
-        mock_usage.assert_called_once_with(mock.sentinel.volume,
+        mock_usage.assert_called_once_with(mock.sentinel.context,
+                                           mock.sentinel.volume,
                                            a='b', c='d')
         mock_rpc.get_notifier.assert_called_once_with('replication', 'host2')
         mock_rpc.get_notifier.return_value.error.assert_called_once_with(
@@ -198,6 +207,7 @@ class NotifyUsageTestCase(test.TestCase):
             'created_at': '2014-12-11T10:10:00',
             'status': 'pause',
             'deleted': '',
+            'metadata': {'fake_snap_meta_key': 'fake_snap_meta_value'},
         }
         usage_info = volume_utils._usage_from_snapshot(raw_snapshot)
         expected_snapshot = {
@@ -211,9 +221,55 @@ class NotifyUsageTestCase(test.TestCase):
             'created_at': '2014-12-11T10:10:00',
             'status': 'pause',
             'deleted': '',
+            'metadata': "{'fake_snap_meta_key': 'fake_snap_meta_value'}",
         }
         self.assertEqual(expected_snapshot, usage_info)
 
+    @mock.patch('cinder.db.volume_glance_metadata_get')
+    def test_usage_from_volume(self, mock_image_metadata):
+        mock_image_metadata.return_value = {'image_id': 'fake_image_id'}
+        raw_volume = {
+            'project_id': '12b0330ec2584a',
+            'user_id': '158cba1b8c2bb6008e',
+            'host': 'fake_host',
+            'availability_zone': 'nova',
+            'volume_type_id': 'fake_volume_type_id',
+            'id': 'fake_volume_id',
+            'size': 1,
+            'display_name': 'test_volume',
+            'created_at': datetime.datetime(2015, 1, 1, 1, 1, 1),
+            'launched_at': datetime.datetime(2015, 1, 1, 1, 1, 1),
+            'snapshot_id': None,
+            'replication_status': None,
+            'replication_extended_status': None,
+            'replication_driver_data': None,
+            'status': 'available',
+            'volume_metadata': {'fake_metadata_key': 'fake_metadata_value'},
+        }
+        usage_info = volume_utils._usage_from_volume(
+            mock.sentinel.context,
+            raw_volume)
+        expected_volume = {
+            'tenant_id': '12b0330ec2584a',
+            'user_id': '158cba1b8c2bb6008e',
+            'host': 'fake_host',
+            'availability_zone': 'nova',
+            'volume_type': 'fake_volume_type_id',
+            'volume_id': 'fake_volume_id',
+            'size': 1,
+            'display_name': 'test_volume',
+            'created_at': '2015-01-01T01:01:01',
+            'launched_at': '2015-01-01T01:01:01',
+            'snapshot_id': None,
+            'replication_status': None,
+            'replication_extended_status': None,
+            'replication_driver_data': None,
+            'status': 'available',
+            'metadata': {'fake_metadata_key': 'fake_metadata_value'},
+            'glance_metadata': {'image_id': 'fake_image_id'},
+        }
+        self.assertEqual(expected_volume, usage_info)
+
     @mock.patch('cinder.volume.utils._usage_from_consistencygroup')
     @mock.patch('cinder.volume.utils.CONF')
     @mock.patch('cinder.volume.utils.rpc')
index d136cd79f0f114086f06cc25de9224a1e9ffe3d5..aa14e7fc99e71f58d743be835df76596d86fda3d 100644 (file)
@@ -26,6 +26,7 @@ from oslo_utils import timeutils
 from oslo_utils import units
 
 from cinder.brick.local_dev import lvm as brick_lvm
+from cinder import db
 from cinder import exception
 from cinder.i18n import _LI, _LW
 from cinder import rpc
@@ -42,7 +43,7 @@ def null_safe_str(s):
     return str(s) if s else ''
 
 
-def _usage_from_volume(volume_ref, **kw):
+def _usage_from_volume(context, volume_ref, **kw):
     now = timeutils.utcnow()
     launched_at = volume_ref['launched_at'] or now
     created_at = volume_ref['created_at'] or now
@@ -61,9 +62,18 @@ def _usage_from_volume(volume_ref, **kw):
         size=volume_ref['size'],
         replication_status=volume_ref['replication_status'],
         replication_extended_status=volume_ref['replication_extended_status'],
-        replication_driver_data=volume_ref['replication_driver_data'],)
+        replication_driver_data=volume_ref['replication_driver_data'],
+        metadata=volume_ref.get('volume_metadata'),)
 
     usage_info.update(kw)
+    try:
+        glance_meta = db.volume_glance_metadata_get(context, volume_ref['id'])
+        if glance_meta:
+            usage_info['glance_metadata'] = glance_meta
+    except exception.GlanceMetadataNotFound:
+        pass
+    except exception.VolumeNotFound:
+        LOG.debug("Can not find volume %s at notify usage", volume_ref['id'])
     return usage_info
 
 
@@ -94,7 +104,7 @@ def notify_about_volume_usage(context, volume, event_suffix,
     if not extra_usage_info:
         extra_usage_info = {}
 
-    usage_info = _usage_from_volume(volume, **extra_usage_info)
+    usage_info = _usage_from_volume(context, volume, **extra_usage_info)
 
     rpc.get_notifier("volume", host).info(context, 'volume.%s' % event_suffix,
                                           usage_info)
@@ -126,7 +136,8 @@ def _usage_from_snapshot(snapshot_ref, **extra_usage_info):
         'display_name': snapshot_ref['display_name'],
         'created_at': str(snapshot_ref['created_at']),
         'status': snapshot_ref['status'],
-        'deleted': null_safe_str(snapshot_ref['deleted'])
+        'deleted': null_safe_str(snapshot_ref['deleted']),
+        'metadata': null_safe_str(snapshot_ref.get('metadata')),
     }
 
     usage_info.update(extra_usage_info)
@@ -156,7 +167,7 @@ def notify_about_replication_usage(context, volume, suffix,
     if not extra_usage_info:
         extra_usage_info = {}
 
-    usage_info = _usage_from_volume(volume,
+    usage_info = _usage_from_volume(context, volume,
                                     **extra_usage_info)
 
     rpc.get_notifier('replication', host).info(context,
@@ -172,7 +183,7 @@ def notify_about_replication_error(context, volume, suffix,
     if not extra_error_info:
         extra_error_info = {}
 
-    usage_info = _usage_from_volume(volume,
+    usage_info = _usage_from_volume(context, volume,
                                     **extra_error_info)
 
     rpc.get_notifier('replication', host).error(context,