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:
parent
6cee8a3d2e
commit
3b20fa0852
@ -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'],
|
||||||
|
@ -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):
|
||||||
|
@ -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):
|
||||||
|
@ -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.
|
||||||
|
@ -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))
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user