From 149e4d64109d3b7a2ac2be19e8fc7c0546f9e542 Mon Sep 17 00:00:00 2001 From: Fei Long Wang Date: Thu, 25 Jul 2013 15:23:45 +0800 Subject: [PATCH] Fix the dict type metadata missing issue Based on current implement, the metadata with dict type will be missed. But some metadata are using dict type, such as the extra properties of Glance images. Fix bug 1203699 Change-Id: Ie13e4e5231c789e0efcadace11347a15741472a1 --- ceilometer/api/controllers/v2.py | 6 ++++-- ceilometer/utils.py | 4 ++-- tests/api/v2/test_list_events_scenarios.py | 5 +++-- tests/api/v2/test_list_meters_scenarios.py | 4 +--- tests/api/v2/test_list_resources_scenarios.py | 11 ++++++----- tests/test_utils.py | 14 ++++++++++++++ 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py index 3d1ea0223..8088c5c78 100644 --- a/ceilometer/api/controllers/v2.py +++ b/ceilometer/api/controllers/v2.py @@ -45,6 +45,7 @@ from ceilometer.openstack.common import log from ceilometer.openstack.common import timeutils from ceilometer import sample from ceilometer import storage +from ceilometer import utils from ceilometer.api import acl @@ -270,8 +271,9 @@ def _flatten_metadata(metadata): """ if metadata: return dict((k, unicode(v)) - for k, v in metadata.iteritems() - if type(v) not in set([list, dict, set])) + for k, v in utils.recursive_keypairs(metadata, + separator='.') + if type(v) not in set([list, set])) return {} diff --git a/ceilometer/utils.py b/ceilometer/utils.py index bf87c1441..60a08e902 100644 --- a/ceilometer/utils.py +++ b/ceilometer/utils.py @@ -27,13 +27,13 @@ import decimal from ceilometer.openstack.common import timeutils -def recursive_keypairs(d): +def recursive_keypairs(d, separator=':'): """Generator that produces sequence of keypairs for nested dictionaries. """ for name, value in sorted(d.iteritems()): if isinstance(value, dict): for subname, subvalue in recursive_keypairs(value): - yield ('%s:%s' % (name, subname), subvalue) + yield ('%s%s%s' % (name, separator, subname), subvalue) elif isinstance(value, (tuple, list)): # When doing a pair of JSON encode/decode operations to the tuple, # the tuple would become list. So we have to generate the value as diff --git a/tests/api/v2/test_list_events_scenarios.py b/tests/api/v2/test_list_events_scenarios.py index 50215a97b..0c93ff324 100644 --- a/tests/api/v2/test_list_events_scenarios.py +++ b/tests/api/v2/test_list_events_scenarios.py @@ -52,7 +52,7 @@ class TestListEvents(FunctionalTest, timestamp=datetime.datetime(2012, 7, 2, 10, 40), resource_metadata={'display_name': 'test-server', 'tag': 'self.counter', - 'ignored_dict': {'key': 'value'}, + 'dict_properties': {'key': 'value'}, 'ignored_list': ['not-returned'], }, source='test_source', @@ -169,6 +169,7 @@ class TestListEvents(FunctionalTest, self.assert_('resource_metadata' in sample) self.assertEqual( list(sorted(sample['resource_metadata'].iteritems())), - [('display_name', 'test-server'), + [('dict_properties.key', 'value'), + ('display_name', 'test-server'), ('tag', 'self.counter'), ]) diff --git a/tests/api/v2/test_list_meters_scenarios.py b/tests/api/v2/test_list_meters_scenarios.py index b86dde528..948d26775 100644 --- a/tests/api/v2/test_list_meters_scenarios.py +++ b/tests/api/v2/test_list_meters_scenarios.py @@ -143,10 +143,8 @@ class TestListMeters(FunctionalTest, self.assertEquals('resource-id4', data[0]['resource_id']) metadata = data[0]['resource_metadata'] self.assertIsNotNone(metadata) - # FIXME (flwang): Based on current implement, the metadata of - # dictionary type can't be shown in the output. See bug 1203699. - # Will add more asserts in the fix of 1203699. self.assertEqual('self.counter4', metadata['tag']) + self.assertEqual('prop_value', metadata['properties.prop_1']) def test_list_meters_metadata_query(self): data = self.get_json('/meters/meter.test', diff --git a/tests/api/v2/test_list_resources_scenarios.py b/tests/api/v2/test_list_resources_scenarios.py index cbbe6de03..d2092d7fc 100644 --- a/tests/api/v2/test_list_resources_scenarios.py +++ b/tests/api/v2/test_list_resources_scenarios.py @@ -411,7 +411,7 @@ class TestListResources(FunctionalTest, timestamp=datetime.datetime(2012, 7, 2, 10, 40), resource_metadata={'display_name': 'test-server', 'tag': 'self.counter', - 'ignored_dict': {'key': 'value'}, + 'dict_properties': {'key': 'value'}, 'ignored_list': ['not-returned'], }, source='test', @@ -425,10 +425,11 @@ class TestListResources(FunctionalTest, data = self.get_json('/resources') metadata = data[0]['metadata'] self.assertEqual( - list(sorted(metadata.iteritems())), - [('display_name', 'test-server'), - ('tag', 'self.counter'), - ]) + [(u'dict_properties.key', u'value'), + (u'display_name', u'test-server'), + (u'tag', u'self.counter') + ], + list(sorted(metadata.iteritems()))) def test_resource_meter_links(self): counter1 = sample.Sample( diff --git a/tests/test_utils.py b/tests/test_utils.py index f551c2e24..36ff228bb 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -53,3 +53,17 @@ class TestUtils(tests_base.TestCase): ('b', 'B'), ('nested:a', 'A'), ('nested:b', 'B')]) + + def test_recursive_keypairs_with_separator(self): + data = {'a': 'A', + 'b': 'B', + 'nested': {'a': 'A', + 'b': 'B', + }, + } + separator = '.' + pairs = list(utils.recursive_keypairs(data, separator)) + self.assertEqual(pairs, [('a', 'A'), + ('b', 'B'), + ('nested.a', 'A'), + ('nested.b', 'B')])