From bf9857e30ecae91f6d279239eaab0a0ff4b190dc Mon Sep 17 00:00:00 2001 From: Fei Long Wang Date: Wed, 31 Jul 2013 23:13:37 +0800 Subject: [PATCH] Fixes dict metadata query issue of HBase Now HBase doesn't support query the metadata with the dictionary type. For example, the metadata of Glance image always has the metadata "properties" which is dictionary and has some attributes, size, kernel id, etc. So this fix will enable the HBase driver of CM to support query like "metadata.properties.tag=test". Fixes bug 1206022 Change-Id: I7fa73cea94a948d47e27492dfb7e3a0e005ccb48 --- ceilometer/storage/impl_hbase.py | 14 +++++++++++-- tests/api/v2/test_list_meters_scenarios.py | 23 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ceilometer/storage/impl_hbase.py b/ceilometer/storage/impl_hbase.py index 991edb07f..ad5ac6fb3 100644 --- a/ceilometer/storage/impl_hbase.py +++ b/ceilometer/storage/impl_hbase.py @@ -449,8 +449,18 @@ class Connection(base.Connection): for k, v in metaquery.iteritems(): message = json.loads(meter['f:message']) metadata = message['resource_metadata'] - if metadata[k.split('.', 1)[1]] != v: - break # if one metaquery doesn't match, break + keys = k.split('.') + # Support the dictionary type of metadata + for key in keys[1:]: + if key in metadata: + metadata = metadata[key] + else: + break + # NOTE (flwang) For multiple level searching, the matadata + # object will be drilled down to check if it's matched + # with the searched value. + if metadata != v: + break else: if limit: limit -= 1 diff --git a/tests/api/v2/test_list_meters_scenarios.py b/tests/api/v2/test_list_meters_scenarios.py index e39192298..b86dde528 100644 --- a/tests/api/v2/test_list_meters_scenarios.py +++ b/tests/api/v2/test_list_meters_scenarios.py @@ -108,7 +108,12 @@ class TestListMeters(FunctionalTest, 'resource-id4', timestamp=datetime.datetime(2012, 7, 2, 10, 43), resource_metadata={'display_name': 'test-server', - 'tag': 'self.counter4'}, + 'tag': 'self.counter4', + 'properties': { + 'prop_1': 'prop_value', + 'prop_2': {'sub_prop_1': + 'sub_prop_value'}} + }, source='test_source')]: msg = rpc.meter_message_from_counter( cnt, @@ -127,6 +132,22 @@ class TestListMeters(FunctionalTest, set(['meter.test', 'meter.mine'])) + def test_list_meters_with_dict_metadata(self): + data = self.get_json('/meters/meter.mine', + q=[{'field': + 'metadata.properties.prop_2.sub_prop_1', + 'op': 'eq', + 'value': 'sub_prop_value', + }]) + self.assertEquals(1, len(data)) + 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']) + def test_list_meters_metadata_query(self): data = self.get_json('/meters/meter.test', q=[{'field': 'metadata.tag',