[openstack-ceilometer] Handle poorly formed individual sensor readings
Eoghan Glynn
eglynn at fedoraproject.org
Thu Oct 23 14:10:05 UTC 2014
commit a22d8847402f9e53a473f7ac0e8c1c74aa4c58d7
Author: Eoghan Glynn <eglynn at redhat.com>
Date: Thu Oct 23 13:56:52 2014 +0000
Handle poorly formed individual sensor readings
Change-Id: I0d25d294ef7c972ce2d82cd8c4b8023bfe297613
...-poorly-formed-individual-sensor-readings.patch | 160 ++++++++++++++++++++
openstack-ceilometer.spec | 9 +-
2 files changed, 168 insertions(+), 1 deletions(-)
---
diff --git a/0001-Handle-poorly-formed-individual-sensor-readings.patch b/0001-Handle-poorly-formed-individual-sensor-readings.patch
new file mode 100644
index 0000000..c9dadc9
--- /dev/null
+++ b/0001-Handle-poorly-formed-individual-sensor-readings.patch
@@ -0,0 +1,160 @@
+From 5b826ea1dc33b58009b16e3663298589d6978f81 Mon Sep 17 00:00:00 2001
+From: Chris Dent <chdent at redhat.com>
+Date: Wed, 15 Oct 2014 17:18:17 +0100
+Subject: [PATCH] Handle poorly formed individual sensor readings
+
+ipmitool returns a series of multiple readings per run. Some of
+these readings may be of a form that parser code cannot handle. The
+desired behavior in this case is for the single reading to be
+dropped and for parsing to continue. This change ensures that
+behavior by continuing through the loop instead of allowing
+exceptions to cause the loop to exit.
+
+Tests have been added which verify the correct behavior.
+
+Note that though there was an opportunity to log each skipped
+reading this would lead to a very large number of log messages as
+many or even most samples from ipmitool are not parsed.
+
+Change-Id: I6a3193d5a6e12c69ca5c548e5fb58d8bc9646348
+Closes-Bug: #1381600
+(cherry picked from commit 8323cfe92af2ad27f6611be0a6887cac12b2c630)
+(cherry picked from commit b1fca33e5f4c5443389d131a212a058d2306ac23)
+---
+ ceilometer/ipmi/pollsters/sensor.py | 11 +++--
+ ceilometer/tests/ipmi/pollsters/base.py | 10 +++--
+ ceilometer/tests/ipmi/pollsters/test_sensor.py | 58 ++++++++++++++++++++++++++
+ 3 files changed, 72 insertions(+), 7 deletions(-)
+
+diff --git a/ceilometer/ipmi/pollsters/sensor.py b/ceilometer/ipmi/pollsters/sensor.py
+index a23e088..a1a4e54 100644
+--- a/ceilometer/ipmi/pollsters/sensor.py
++++ b/ceilometer/ipmi/pollsters/sensor.py
+@@ -54,19 +54,24 @@ class SensorPollster(plugin.PollsterBase):
+ sensor_type_data = self._get_sensor_types(stats, self.METRIC)
+
+ for sensor_data in sensor_type_data:
++ # Continue if sensor_data is not parseable.
+ try:
+ sensor_reading = sensor_data['Sensor Reading']
++ sensor_id = sensor_data['Sensor ID']
+ except KeyError:
+- raise InvalidSensorData("missing 'Sensor Reading'")
++ continue
+
+ if not parser.validate_reading(sensor_reading):
+ continue
+
+- volume, unit = parser.parse_reading(sensor_reading)
++ try:
++ volume, unit = parser.parse_reading(sensor_reading)
++ except parser.InvalidSensorData:
++ continue
+
+ resource_id = '%(host)s-%(sensor-id)s' % {
+ 'host': CONF.host,
+- 'sensor-id': parser.transform_id(sensor_data['Sensor ID'])
++ 'sensor-id': parser.transform_id(sensor_id)
+ }
+
+ metadata = {
+diff --git a/ceilometer/tests/ipmi/pollsters/base.py b/ceilometer/tests/ipmi/pollsters/base.py
+index 575c54d..5b72edf 100644
+--- a/ceilometer/tests/ipmi/pollsters/base.py
++++ b/ceilometer/tests/ipmi/pollsters/base.py
+@@ -57,13 +57,15 @@ class TestPollsterBase(base.BaseTestCase):
+
+ self.pollster = self.make_pollster()
+
+- def _verify_metering(self, length, expected_vol, node):
++ def _verify_metering(self, length, expected_vol=None, node=None):
+ cache = {}
+ resources = {}
+
+ samples = list(self.pollster.get_samples(self.mgr, cache, resources))
+ 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))
++ if expected_vol:
++ self.assertTrue(any(s.volume == expected_vol for s in samples))
++ if node:
++ self.assertTrue(any(s.resource_metadata['node'] == node
++ for s in samples))
+diff --git a/ceilometer/tests/ipmi/pollsters/test_sensor.py b/ceilometer/tests/ipmi/pollsters/test_sensor.py
+index ad83391..3b4ab31 100644
+--- a/ceilometer/tests/ipmi/pollsters/test_sensor.py
++++ b/ceilometer/tests/ipmi/pollsters/test_sensor.py
+@@ -41,6 +41,10 @@ VOLTAGE_SENSOR_DATA = {
+ 'Voltage': ipmi_test_data.VOLTAGE_DATA
+ }
+
++MISSING_SENSOR_DATA = ipmi_test_data.MISSING_SENSOR['payload']['payload']
++MALFORMED_SENSOR_DATA = ipmi_test_data.BAD_SENSOR['payload']['payload']
++MISSING_ID_SENSOR_DATA = ipmi_test_data.NO_SENSOR_ID['payload']['payload']
++
+
+ class TestTemperatureSensorPollster(base.TestPollsterBase):
+
+@@ -61,6 +65,60 @@ class TestTemperatureSensorPollster(base.TestPollsterBase):
+ self._verify_metering(10, float(32), CONF.host)
+
+
++class TestMissingSensorData(base.TestPollsterBase):
++
++ def fake_sensor_data(self, sensor_type):
++ return MISSING_SENSOR_DATA
++
++ def fake_data(self):
++ # No use for Sensor test
++ return None
++
++ def make_pollster(self):
++ return sensor.TemperatureSensorPollster()
++
++ @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
++ def test_get_samples(self):
++ self._test_get_samples()
++ self._verify_metering(0)
++
++
++class TestMalformedSensorData(base.TestPollsterBase):
++
++ def fake_sensor_data(self, sensor_type):
++ return MALFORMED_SENSOR_DATA
++
++ def fake_data(self):
++ # No use for Sensor test
++ return None
++
++ def make_pollster(self):
++ return sensor.TemperatureSensorPollster()
++
++ @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
++ def test_get_samples(self):
++ self._test_get_samples()
++ self._verify_metering(0)
++
++
++class TestMissingSensorId(base.TestPollsterBase):
++
++ def fake_sensor_data(self, sensor_type):
++ return MISSING_ID_SENSOR_DATA
++
++ def fake_data(self):
++ # No use for Sensor test
++ return None
++
++ def make_pollster(self):
++ return sensor.TemperatureSensorPollster()
++
++ @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
++ def test_get_samples(self):
++ self._test_get_samples()
++ self._verify_metering(0)
++
++
+ class TestFanSensorPollster(base.TestPollsterBase):
+
+ def fake_sensor_data(self, sensor_type):
diff --git a/openstack-ceilometer.spec b/openstack-ceilometer.spec
index c60f935..d232765 100644
--- a/openstack-ceilometer.spec
+++ b/openstack-ceilometer.spec
@@ -4,7 +4,7 @@
Name: openstack-ceilometer
Version: 2014.2
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: OpenStack measurement collection service
Group: Applications/System
@@ -16,6 +16,8 @@ Source2: %{pypi_name}.logrotate
Source3: %{pypi_name}.conf.sample
Source4: ceilometer-rootwrap-sudoers
+Patch0001: 0001-Handle-poorly-formed-individual-sensor-readings.patch
+
%if 0%{?rhel} && 0%{?rhel} <= 6
Source10: %{name}-api.init
Source100: %{name}-api.upstart
@@ -286,6 +288,8 @@ This package contains documentation files for ceilometer.
%prep
%setup -q -n ceilometer-%{version}
+%patch0001 -p1
+
find . \( -name .gitignore -o -name .placeholder \) -delete
find ceilometer -name \*.py -exec sed -i '/\/usr\/bin\/env python/{d;q}' {} +
@@ -757,6 +761,9 @@ fi
%changelog
+* Thu Oct 23 2014 Eoghan Glynn <eglynn at redhat.com> 2014.2-2
+- Handle poorly formed individual sensor readings
+
* Mon Oct 20 2014 Eoghan Glynn <eglynn at redhat.com> 2014.2-1
- Update to upstream 2014.2 (Juno release)
More information about the scm-commits
mailing list