Notification with volume and snapshot metadata

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
This commit is contained in:
wanghao 2015-05-06 12:08:00 +08:00
parent b6681fb3fb
commit 7d63c25c70
3 changed files with 82 additions and 13 deletions

View 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]

View File

@ -15,7 +15,10 @@
"""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')

View 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,