From 3b20fa08527170aaca38253277feedf0f2d11217 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Mon, 6 Oct 2014 20:00:08 +0100 Subject: [PATCH] Include a 'node' key and value in ipmi metadata The ipmi meters use resource_ids which make it challenging to select information for all the sensors of a particular type. This change adds metadata that identifies the physical node on which a sensor exists. There are still remaining issues with the naming of ipmi and sensor-related meters that will need to be addressed separately. Closes-Bug: 1377157 Change-Id: Ib53755112e4757aa53ab60079f3c555e21a72b63 --- ceilometer/ipmi/notifications/ironic.py | 1 + ceilometer/ipmi/pollsters/node.py | 6 +++++- ceilometer/ipmi/pollsters/sensor.py | 6 +++++- ceilometer/tests/ipmi/notifications/test_ironic.py | 5 ++++- ceilometer/tests/ipmi/pollsters/base.py | 4 +++- ceilometer/tests/ipmi/pollsters/test_node.py | 9 +++++++-- ceilometer/tests/ipmi/pollsters/test_sensor.py | 12 ++++++++---- 7 files changed, 33 insertions(+), 10 deletions(-) diff --git a/ceilometer/ipmi/notifications/ironic.py b/ceilometer/ipmi/notifications/ironic.py index 4e37eeaa76..f33571469e 100644 --- a/ceilometer/ipmi/notifications/ironic.py +++ b/ceilometer/ipmi/notifications/ironic.py @@ -97,6 +97,7 @@ class SensorNotification(plugin.NotificationBase): def _package_payload(self, message, payload): # NOTE(chdent): How much of the payload should we keep? + payload['node'] = message['payload']['node_uuid'] info = {'publisher_id': message['publisher_id'], 'timestamp': message['payload']['timestamp'], 'event_type': message['payload']['event_type'], diff --git a/ceilometer/ipmi/pollsters/node.py b/ceilometer/ipmi/pollsters/node.py index a04c375049..9a2cd238e3 100644 --- a/ceilometer/ipmi/pollsters/node.py +++ b/ceilometer/ipmi/pollsters/node.py @@ -44,6 +44,10 @@ class _Base(plugin.PollsterBase): def get_samples(self, manager, cache, resources): stats = self.read_data() + metadata = { + 'node': CONF.host + } + if stats: data = node_manager._hex(stats["Current_value"]) @@ -56,7 +60,7 @@ class _Base(plugin.PollsterBase): project_id=None, resource_id=CONF.host, timestamp=timeutils.utcnow().isoformat(), - resource_metadata=None) + resource_metadata=metadata) class TemperaturePollster(_Base): diff --git a/ceilometer/ipmi/pollsters/sensor.py b/ceilometer/ipmi/pollsters/sensor.py index 837aec3a73..a23e088ad7 100644 --- a/ceilometer/ipmi/pollsters/sensor.py +++ b/ceilometer/ipmi/pollsters/sensor.py @@ -69,6 +69,10 @@ class SensorPollster(plugin.PollsterBase): 'sensor-id': parser.transform_id(sensor_data['Sensor ID']) } + metadata = { + 'node': CONF.host + } + yield sample.Sample( name='hardware.ipmi.%s' % self.METRIC.lower(), type=sample.TYPE_GAUGE, @@ -78,7 +82,7 @@ class SensorPollster(plugin.PollsterBase): project_id=None, resource_id=resource_id, timestamp=timeutils.utcnow().isoformat(), - resource_metadata=None) + resource_metadata=metadata) class TemperatureSensorPollster(SensorPollster): diff --git a/ceilometer/tests/ipmi/notifications/test_ironic.py b/ceilometer/tests/ipmi/notifications/test_ironic.py index 81eecfd656..82fb9dda20 100644 --- a/ceilometer/tests/ipmi/notifications/test_ironic.py +++ b/ceilometer/tests/ipmi/notifications/test_ironic.py @@ -30,7 +30,7 @@ class TestNotifications(base.BaseTestCase): def test_ipmi_temperature_notification(self): """Test IPMI Temperature sensor data. - Based on the above test data the expected sample for a single + Based on the above ipmi_testdata the expected sample for a single temperature reading has:: * a resource_id composed from the node_uuid Sensor ID @@ -38,6 +38,7 @@ class TestNotifications(base.BaseTestCase): * a volume from the first chunk of the Sensor Reading * a unit from the last chunk of the Sensor Reading * some readings are skipped if the value is 'Disabled' + * metatata with the node id """ processor = ipmi.TemperatureSensorNotification(None) counters = dict([(counter.resource_id, counter) for counter in @@ -56,6 +57,8 @@ class TestNotifications(base.BaseTestCase): self.assertEqual('hardware.ipmi.temperature', test_counter.name) self.assertEqual('hardware.ipmi.metrics.update', test_counter.resource_metadata['event_type']) + self.assertEqual('f4982fd2-2f2b-4bb5-9aff-48aac801d1ad', + test_counter.resource_metadata['node']) def test_ipmi_current_notification(self): """Test IPMI Current sensor data. diff --git a/ceilometer/tests/ipmi/pollsters/base.py b/ceilometer/tests/ipmi/pollsters/base.py index 76d0e2603f..575c54d36a 100644 --- a/ceilometer/tests/ipmi/pollsters/base.py +++ b/ceilometer/tests/ipmi/pollsters/base.py @@ -57,7 +57,7 @@ class TestPollsterBase(base.BaseTestCase): self.pollster = self.make_pollster() - def _verify_metering(self, length, expected_vol): + def _verify_metering(self, length, expected_vol, node): cache = {} resources = {} @@ -65,3 +65,5 @@ class TestPollsterBase(base.BaseTestCase): self.assertEqual(length, len(samples)) self.assertTrue(any(s.volume == expected_vol for s in samples)) + self.assertTrue(any(s.resource_metadata['node'] == node + for s in samples)) diff --git a/ceilometer/tests/ipmi/pollsters/test_node.py b/ceilometer/tests/ipmi/pollsters/test_node.py index 296e1a1269..16f546e77e 100644 --- a/ceilometer/tests/ipmi/pollsters/test_node.py +++ b/ceilometer/tests/ipmi/pollsters/test_node.py @@ -15,11 +15,16 @@ # under the License. import mock +from oslo.config import cfg from ceilometer.ipmi.pollsters import node from ceilometer.tests.ipmi.pollsters import base +CONF = cfg.CONF +CONF.import_opt('host', 'ceilometer.service') + + class TestPowerPollster(base.TestPollsterBase): def fake_data(self): @@ -38,7 +43,7 @@ class TestPowerPollster(base.TestPollsterBase): self._test_get_samples() # only one sample, and value is 19(0x13 as current_value) - self._verify_metering(1, 19) + self._verify_metering(1, 19, CONF.host) class TestTemperaturePollster(base.TestPollsterBase): @@ -59,4 +64,4 @@ class TestTemperaturePollster(base.TestPollsterBase): self._test_get_samples() # only one sample, and value is 35(0x23 as current_value) - self._verify_metering(1, 35) + self._verify_metering(1, 35, CONF.host) diff --git a/ceilometer/tests/ipmi/pollsters/test_sensor.py b/ceilometer/tests/ipmi/pollsters/test_sensor.py index eb7c9a7f7d..ad8339176b 100644 --- a/ceilometer/tests/ipmi/pollsters/test_sensor.py +++ b/ceilometer/tests/ipmi/pollsters/test_sensor.py @@ -15,12 +15,16 @@ # under the License. import mock +from oslo.config import cfg from ceilometer.ipmi.pollsters import sensor from ceilometer.tests.ipmi.notifications import ipmi_test_data from ceilometer.tests.ipmi.pollsters import base +CONF = cfg.CONF +CONF.import_opt('host', 'ceilometer.service') + TEMPERATURE_SENSOR_DATA = { 'Temperature': ipmi_test_data.TEMPERATURE_DATA } @@ -54,7 +58,7 @@ class TestTemperatureSensorPollster(base.TestPollsterBase): def test_get_samples(self): self._test_get_samples() - self._verify_metering(10, float(32)) + self._verify_metering(10, float(32), CONF.host) class TestFanSensorPollster(base.TestPollsterBase): @@ -73,7 +77,7 @@ class TestFanSensorPollster(base.TestPollsterBase): def test_get_samples(self): self._test_get_samples() - self._verify_metering(12, float(7140)) + self._verify_metering(12, float(7140), CONF.host) class TestCurrentSensorPollster(base.TestPollsterBase): @@ -92,7 +96,7 @@ class TestCurrentSensorPollster(base.TestPollsterBase): def test_get_samples(self): self._test_get_samples() - self._verify_metering(1, float(130)) + self._verify_metering(1, float(130), CONF.host) class TestVoltageSensorPollster(base.TestPollsterBase): @@ -111,4 +115,4 @@ class TestVoltageSensorPollster(base.TestPollsterBase): def test_get_samples(self): self._test_get_samples() - self._verify_metering(4, float(3.309)) + self._verify_metering(4, float(3.309), CONF.host)