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
This commit is contained in:
Chris Dent 2014-10-06 20:00:08 +01:00
parent 6cee8a3d2e
commit 3b20fa0852
7 changed files with 33 additions and 10 deletions

View File

@ -97,6 +97,7 @@ class SensorNotification(plugin.NotificationBase):
def _package_payload(self, message, payload): def _package_payload(self, message, payload):
# NOTE(chdent): How much of the payload should we keep? # NOTE(chdent): How much of the payload should we keep?
payload['node'] = message['payload']['node_uuid']
info = {'publisher_id': message['publisher_id'], info = {'publisher_id': message['publisher_id'],
'timestamp': message['payload']['timestamp'], 'timestamp': message['payload']['timestamp'],
'event_type': message['payload']['event_type'], 'event_type': message['payload']['event_type'],

View File

@ -44,6 +44,10 @@ class _Base(plugin.PollsterBase):
def get_samples(self, manager, cache, resources): def get_samples(self, manager, cache, resources):
stats = self.read_data() stats = self.read_data()
metadata = {
'node': CONF.host
}
if stats: if stats:
data = node_manager._hex(stats["Current_value"]) data = node_manager._hex(stats["Current_value"])
@ -56,7 +60,7 @@ class _Base(plugin.PollsterBase):
project_id=None, project_id=None,
resource_id=CONF.host, resource_id=CONF.host,
timestamp=timeutils.utcnow().isoformat(), timestamp=timeutils.utcnow().isoformat(),
resource_metadata=None) resource_metadata=metadata)
class TemperaturePollster(_Base): class TemperaturePollster(_Base):

View File

@ -69,6 +69,10 @@ class SensorPollster(plugin.PollsterBase):
'sensor-id': parser.transform_id(sensor_data['Sensor ID']) 'sensor-id': parser.transform_id(sensor_data['Sensor ID'])
} }
metadata = {
'node': CONF.host
}
yield sample.Sample( yield sample.Sample(
name='hardware.ipmi.%s' % self.METRIC.lower(), name='hardware.ipmi.%s' % self.METRIC.lower(),
type=sample.TYPE_GAUGE, type=sample.TYPE_GAUGE,
@ -78,7 +82,7 @@ class SensorPollster(plugin.PollsterBase):
project_id=None, project_id=None,
resource_id=resource_id, resource_id=resource_id,
timestamp=timeutils.utcnow().isoformat(), timestamp=timeutils.utcnow().isoformat(),
resource_metadata=None) resource_metadata=metadata)
class TemperatureSensorPollster(SensorPollster): class TemperatureSensorPollster(SensorPollster):

View File

@ -30,7 +30,7 @@ class TestNotifications(base.BaseTestCase):
def test_ipmi_temperature_notification(self): def test_ipmi_temperature_notification(self):
"""Test IPMI Temperature sensor data. """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:: temperature reading has::
* a resource_id composed from the node_uuid Sensor ID * 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 volume from the first chunk of the Sensor Reading
* a unit from the last chunk of the Sensor Reading * a unit from the last chunk of the Sensor Reading
* some readings are skipped if the value is 'Disabled' * some readings are skipped if the value is 'Disabled'
* metatata with the node id
""" """
processor = ipmi.TemperatureSensorNotification(None) processor = ipmi.TemperatureSensorNotification(None)
counters = dict([(counter.resource_id, counter) for counter in 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.temperature', test_counter.name)
self.assertEqual('hardware.ipmi.metrics.update', self.assertEqual('hardware.ipmi.metrics.update',
test_counter.resource_metadata['event_type']) test_counter.resource_metadata['event_type'])
self.assertEqual('f4982fd2-2f2b-4bb5-9aff-48aac801d1ad',
test_counter.resource_metadata['node'])
def test_ipmi_current_notification(self): def test_ipmi_current_notification(self):
"""Test IPMI Current sensor data. """Test IPMI Current sensor data.

View File

@ -57,7 +57,7 @@ class TestPollsterBase(base.BaseTestCase):
self.pollster = self.make_pollster() self.pollster = self.make_pollster()
def _verify_metering(self, length, expected_vol): def _verify_metering(self, length, expected_vol, node):
cache = {} cache = {}
resources = {} resources = {}
@ -65,3 +65,5 @@ class TestPollsterBase(base.BaseTestCase):
self.assertEqual(length, len(samples)) self.assertEqual(length, len(samples))
self.assertTrue(any(s.volume == expected_vol for s in samples)) self.assertTrue(any(s.volume == expected_vol for s in samples))
self.assertTrue(any(s.resource_metadata['node'] == node
for s in samples))

View File

@ -15,11 +15,16 @@
# under the License. # under the License.
import mock import mock
from oslo.config import cfg
from ceilometer.ipmi.pollsters import node from ceilometer.ipmi.pollsters import node
from ceilometer.tests.ipmi.pollsters import base from ceilometer.tests.ipmi.pollsters import base
CONF = cfg.CONF
CONF.import_opt('host', 'ceilometer.service')
class TestPowerPollster(base.TestPollsterBase): class TestPowerPollster(base.TestPollsterBase):
def fake_data(self): def fake_data(self):
@ -38,7 +43,7 @@ class TestPowerPollster(base.TestPollsterBase):
self._test_get_samples() self._test_get_samples()
# only one sample, and value is 19(0x13 as current_value) # 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): class TestTemperaturePollster(base.TestPollsterBase):
@ -59,4 +64,4 @@ class TestTemperaturePollster(base.TestPollsterBase):
self._test_get_samples() self._test_get_samples()
# only one sample, and value is 35(0x23 as current_value) # only one sample, and value is 35(0x23 as current_value)
self._verify_metering(1, 35) self._verify_metering(1, 35, CONF.host)

View File

@ -15,12 +15,16 @@
# under the License. # under the License.
import mock import mock
from oslo.config import cfg
from ceilometer.ipmi.pollsters import sensor from ceilometer.ipmi.pollsters import sensor
from ceilometer.tests.ipmi.notifications import ipmi_test_data from ceilometer.tests.ipmi.notifications import ipmi_test_data
from ceilometer.tests.ipmi.pollsters import base from ceilometer.tests.ipmi.pollsters import base
CONF = cfg.CONF
CONF.import_opt('host', 'ceilometer.service')
TEMPERATURE_SENSOR_DATA = { TEMPERATURE_SENSOR_DATA = {
'Temperature': ipmi_test_data.TEMPERATURE_DATA 'Temperature': ipmi_test_data.TEMPERATURE_DATA
} }
@ -54,7 +58,7 @@ class TestTemperatureSensorPollster(base.TestPollsterBase):
def test_get_samples(self): def test_get_samples(self):
self._test_get_samples() self._test_get_samples()
self._verify_metering(10, float(32)) self._verify_metering(10, float(32), CONF.host)
class TestFanSensorPollster(base.TestPollsterBase): class TestFanSensorPollster(base.TestPollsterBase):
@ -73,7 +77,7 @@ class TestFanSensorPollster(base.TestPollsterBase):
def test_get_samples(self): def test_get_samples(self):
self._test_get_samples() self._test_get_samples()
self._verify_metering(12, float(7140)) self._verify_metering(12, float(7140), CONF.host)
class TestCurrentSensorPollster(base.TestPollsterBase): class TestCurrentSensorPollster(base.TestPollsterBase):
@ -92,7 +96,7 @@ class TestCurrentSensorPollster(base.TestPollsterBase):
def test_get_samples(self): def test_get_samples(self):
self._test_get_samples() self._test_get_samples()
self._verify_metering(1, float(130)) self._verify_metering(1, float(130), CONF.host)
class TestVoltageSensorPollster(base.TestPollsterBase): class TestVoltageSensorPollster(base.TestPollsterBase):
@ -111,4 +115,4 @@ class TestVoltageSensorPollster(base.TestPollsterBase):
def test_get_samples(self): def test_get_samples(self):
self._test_get_samples() self._test_get_samples()
self._verify_metering(4, float(3.309)) self._verify_metering(4, float(3.309), CONF.host)