From 35f65339992c320b8aab89dab2517281d225d01b Mon Sep 17 00:00:00 2001 From: gord chung Date: Mon, 12 Feb 2018 11:12:27 -0500 Subject: [PATCH] avoid verbose tracebacks on known errors - log that no pollsters loaded rather than throwing error - ipmi are expected to be missing as note says, just debug logs with details rather than massive traceback. Closes-Bug: #1747536 Change-Id: Ib592c84dca017e94c66aad0170f0317e514fd747 --- ceilometer/ipmi/pollsters/node.py | 3 +- ceilometer/ipmi/pollsters/sensor.py | 3 +- ceilometer/polling/manager.py | 13 ++---- ceilometer/polling/plugin_base.py | 3 +- ceilometer/tests/unit/polling/test_manager.py | 41 +++++++++---------- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/ceilometer/ipmi/pollsters/node.py b/ceilometer/ipmi/pollsters/node.py index 088bc783b9..16e85a9b04 100644 --- a/ceilometer/ipmi/pollsters/node.py +++ b/ceilometer/ipmi/pollsters/node.py @@ -36,7 +36,8 @@ class _Base(plugin_base.PollsterBase): # Do not load this extension if no NM support if self.nodemanager.nm_version == 0: - raise plugin_base.ExtensionLoadError() + raise plugin_base.ExtensionLoadError( + "NodeManager not supported on host") @property def default_discovery(self): diff --git a/ceilometer/ipmi/pollsters/sensor.py b/ceilometer/ipmi/pollsters/sensor.py index bac8c69fc0..7b534faf01 100644 --- a/ceilometer/ipmi/pollsters/sensor.py +++ b/ceilometer/ipmi/pollsters/sensor.py @@ -38,7 +38,8 @@ class SensorPollster(plugin_base.PollsterBase): # Do not load this extension if no IPMI support if not self.ipmi.ipmi_support: - raise plugin_base.ExtensionLoadError() + raise plugin_base.ExtensionLoadError( + "IPMITool not supported on host") @property def default_discovery(self): diff --git a/ceilometer/polling/manager.py b/ceilometer/polling/manager.py index 7de9be46d2..5a31fe6a77 100644 --- a/ceilometer/polling/manager.py +++ b/ceilometer/polling/manager.py @@ -69,13 +69,6 @@ def hash_of_set(s): return str(hash(frozenset(s))) -class EmptyPollstersList(Exception): - def __init__(self): - msg = ('No valid pollsters can be loaded with the startup parameter' - ' polling-namespaces.') - super(EmptyPollstersList, self).__init__(msg) - - class PollingException(agent.ConfigException): def __init__(self, message, cfg): super(PollingException, self).__init__('Polling', message, cfg) @@ -256,7 +249,8 @@ class AgentManager(cotyledon.Service): itertools.chain(*list(extensions_fb))) if self.extensions == []: - raise EmptyPollstersList() + LOG.warning('No valid pollsters can be loaded from %s ' + 'namespaces', namespaces) discoveries = (self._extensions('discover', namespace, self.conf).extensions @@ -292,7 +286,8 @@ class AgentManager(cotyledon.Service): # Extension raising ExtensionLoadError can be ignored, # and ignore anything we can't import as a safety measure. if isinstance(exc, plugin_base.ExtensionLoadError): - LOG.exception("Skip loading extension for %s", ep.name) + LOG.debug("Skip loading extension for %s: %s", + ep.name, exc.msg) return show_exception = (LOG.isEnabledFor(logging.DEBUG) diff --git a/ceilometer/polling/plugin_base.py b/ceilometer/polling/plugin_base.py index 38f33ede02..685a86a470 100644 --- a/ceilometer/polling/plugin_base.py +++ b/ceilometer/polling/plugin_base.py @@ -32,7 +32,8 @@ class ExtensionLoadError(Exception): to setup required HW/SW dependency. Any exception from it would be propagated as ExtensionLoadError, then skip loading this pollster. """ - pass + def __init__(self, msg=None): + self.msg = msg class PollsterPermanentError(Exception): diff --git a/ceilometer/tests/unit/polling/test_manager.py b/ceilometer/tests/unit/polling/test_manager.py index ce94edff03..d2869e70d0 100644 --- a/ceilometer/tests/unit/polling/test_manager.py +++ b/ceilometer/tests/unit/polling/test_manager.py @@ -103,42 +103,39 @@ class TestManager(base.BaseTestCase): # Skip loading pollster upon ExtensionLoadError @mock.patch('ceilometer.ipmi.pollsters.node._Base.__init__', - mock.Mock(side_effect=plugin_base.ExtensionLoadError)) - @mock.patch('ceilometer.ipmi.pollsters.sensor.SensorPollster.__init__', - mock.Mock(return_value=None)) + mock.Mock(side_effect=plugin_base.ExtensionLoadError( + 'NodeManager not supported on host'))) @mock.patch('ceilometer.polling.manager.LOG') def test_load_failed_plugins(self, LOG): # Here we additionally check that namespaces will be converted to the # list if param was not set as a list. - try: - manager.AgentManager(0, self.conf, - namespaces='ipmi') - except manager.EmptyPollstersList: - err_msg = 'Skip loading extension for %s' - pollster_names = [ - 'power', 'temperature', 'outlet_temperature', - 'airflow', 'cups', 'cpu_util', 'mem_util', 'io_util'] - calls = [mock.call(err_msg, 'hardware.ipmi.node.%s' % n) - for n in pollster_names] - LOG.exception.assert_has_calls(calls=calls, any_order=True) + manager.AgentManager(0, self.conf, namespaces='ipmi') + err_msg = 'Skip loading extension for %s: %s' + pollster_names = [ + 'power', 'temperature', 'outlet_temperature', + 'airflow', 'cups', 'cpu_util', 'mem_util', 'io_util'] + calls = [mock.call(err_msg, 'hardware.ipmi.node.%s' % n, + 'NodeManager not supported on host') + for n in pollster_names] + LOG.debug.assert_has_calls(calls=calls[:2], any_order=True) # Skip loading pollster upon ImportError @mock.patch('ceilometer.ipmi.pollsters.node._Base.__init__', mock.Mock(side_effect=ImportError)) @mock.patch('ceilometer.ipmi.pollsters.sensor.SensorPollster.__init__', - mock.Mock(return_value=None)) - def test_import_error_in_plugin(self): - self.assertRaisesRegex( - manager.EmptyPollstersList, - 'No valid pollsters can be loaded with the startup parameter' - ' polling-namespaces.', - manager.AgentManager, 0, self.conf, {"namespaces": ['ipmi']}) + mock.Mock(side_effect=ImportError)) + @mock.patch('ceilometer.polling.manager.LOG') + def test_import_error_in_plugin(self, LOG): + namespaces = ['ipmi'] + manager.AgentManager(0, self.conf, namespaces=namespaces) + LOG.warning.assert_called_with( + 'No valid pollsters can be loaded from %s namespaces', namespaces) # Exceptions other than ExtensionLoadError are propagated @mock.patch('ceilometer.ipmi.pollsters.node._Base.__init__', mock.Mock(side_effect=PollingException)) @mock.patch('ceilometer.ipmi.pollsters.sensor.SensorPollster.__init__', - mock.Mock(return_value=None)) + mock.Mock(side_effect=PollingException)) def test_load_exceptional_plugins(self): self.assertRaises(PollingException, manager.AgentManager,