diff --git a/ceilometer/declarative.py b/ceilometer/declarative.py index c4b907c07b..47ebbe73be 100644 --- a/ceilometer/declarative.py +++ b/ceilometer/declarative.py @@ -26,8 +26,21 @@ LOG = log.getLogger(__name__) class DefinitionException(Exception): def __init__(self, message, definition_cfg): - super(DefinitionException, self).__init__(message) - self.definition_cfg = definition_cfg + msg = '%s %s: %s' % (self.__class__.__name__, definition_cfg, message) + super(DefinitionException, self).__init__(msg) + self.brief_message = message + + +class MeterDefinitionException(DefinitionException): + pass + + +class EventDefinitionException(DefinitionException): + pass + + +class ResourceDefinitionException(DefinitionException): + pass class Definition(object): diff --git a/ceilometer/dispatcher/gnocchi.py b/ceilometer/dispatcher/gnocchi.py index 2e1f96653e..54eacf835f 100644 --- a/ceilometer/dispatcher/gnocchi.py +++ b/ceilometer/dispatcher/gnocchi.py @@ -73,12 +73,6 @@ def cache_key_mangler(key): return uuid.uuid5(CACHE_NAMESPACE, key).hex -class ResourcesDefinitionException(Exception): - def __init__(self, message, definition_cfg): - msg = '%s %s: %s' % (self.__class__.__name__, definition_cfg, message) - super(ResourcesDefinitionException, self).__init__(msg) - - class ResourcesDefinition(object): MANDATORY_FIELDS = {'resource_type': six.string_types, @@ -90,10 +84,10 @@ class ResourcesDefinition(object): for field, field_type in self.MANDATORY_FIELDS.items(): if field not in self.cfg: - raise declarative.DefinitionException( + raise declarative.ResourceDefinitionException( _LE("Required field %s not specified") % field, self.cfg) if not isinstance(self.cfg[field], field_type): - raise declarative.DefinitionException( + raise declarative.ResourceDefinitionException( _LE("Required field %(field)s should be a %(type)s") % {'field': field, 'type': field_type}, self.cfg) diff --git a/ceilometer/event/converter.py b/ceilometer/event/converter.py index 62b3fa4b0a..6806909c0c 100644 --- a/ceilometer/event/converter.py +++ b/ceilometer/event/converter.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from debtcollector import moves from oslo_config import cfg from oslo_log import log from oslo_utils import fnmatch @@ -44,12 +43,6 @@ cfg.CONF.register_opts(OPTS, group='event') LOG = log.getLogger(__name__) -EventDefinitionException = moves.moved_class(declarative.DefinitionException, - 'EventDefinitionException', - __name__, - version=6.0, - removal_version="?") - class TraitDefinition(declarative.Definition): def __init__(self, name, trait_cfg, plugin_manager): @@ -58,7 +51,7 @@ class TraitDefinition(declarative.Definition): if isinstance(trait_cfg, dict) else 'text') self.trait_type = models.Trait.get_type_by_name(type_name) if self.trait_type is None: - raise declarative.DefinitionException( + raise declarative.EventDefinitionException( _("Invalid trait type '%(type)s' for trait %(trait)s") % dict(type=type_name, trait=name), self.cfg) @@ -102,7 +95,7 @@ class EventDefinition(object): event_type = definition_cfg['event_type'] traits = definition_cfg['traits'] except KeyError as err: - raise declarative.DefinitionException( + raise declarative.EventDefinitionException( _("Required field %s not specified") % err.args[0], self.cfg) if isinstance(event_type, six.string_types): diff --git a/ceilometer/hardware/pollsters/generic.py b/ceilometer/hardware/pollsters/generic.py index e1f3f62d6a..86245204da 100644 --- a/ceilometer/hardware/pollsters/generic.py +++ b/ceilometer/hardware/pollsters/generic.py @@ -40,17 +40,6 @@ cfg.CONF.register_opts(OPTS, group='hardware') LOG = log.getLogger(__name__) -class MeterDefinitionException(Exception): - def __init__(self, message, definition_cfg): - super(MeterDefinitionException, self).__init__(message) - self.message = message - self.definition_cfg = definition_cfg - - def __str__(self): - return '%s %s: %s' % (self.__class__.__name__, - self.definition_cfg, self.message) - - class MeterDefinition(object): required_fields = ['name', 'unit', 'type'] @@ -65,10 +54,10 @@ class MeterDefinition(object): LOG.warning(_LW("Ignore unrecognized field %s"), fname) for fname in self.required_fields: if not getattr(self, fname, None): - raise MeterDefinitionException( + raise declarative.MeterDefinitionException( _LE("Missing field %s") % fname, self.cfg) if self.type not in sample.TYPES: - raise MeterDefinitionException( + raise declarative.MeterDefinitionException( _LE("Unrecognized type value %s") % self.type, self.cfg) @@ -223,8 +212,7 @@ def load_definition(config_def): try: meter = MeterDefinition(meter_def) mappings[meter.name] = meter - except MeterDefinitionException as me: - errmsg = (_LE("Error loading meter definition : %(err)s") - % dict(err=me.message)) - LOG.error(errmsg) + except declarative.DefinitionException as e: + errmsg = _LE("Error loading meter definition: %s") + LOG.error(errmsg, e.brief_message) return mappings diff --git a/ceilometer/meter/notifications.py b/ceilometer/meter/notifications.py index 80ebd3ead4..efb5721330 100644 --- a/ceilometer/meter/notifications.py +++ b/ceilometer/meter/notifications.py @@ -15,7 +15,6 @@ import itertools import pkg_resources import six -from debtcollector import moves from oslo_config import cfg from oslo_log import log import oslo_messaging @@ -41,13 +40,6 @@ cfg.CONF.import_opt('disable_non_metric_meters', 'ceilometer.notification', LOG = log.getLogger(__name__) -MeterDefinitionException = moves.moved_class(declarative.DefinitionException, - 'MeterDefinitionException', - __name__, - version=6.0, - removal_version="?") - - class MeterDefinition(object): SAMPLE_ATTRIBUTES = ["name", "type", "volume", "unit", "timestamp", @@ -61,7 +53,7 @@ class MeterDefinition(object): missing = [field for field in self.REQUIRED_FIELDS if not self.cfg.get(field)] if missing: - raise declarative.DefinitionException( + raise declarative.MeterDefinitionException( _LE("Required fields %s not specified") % missing, self.cfg) self._event_type = self.cfg.get('event_type') @@ -70,7 +62,7 @@ class MeterDefinition(object): if ('type' not in self.cfg.get('lookup', []) and self.cfg['type'] not in sample.TYPES): - raise declarative.DefinitionException( + raise declarative.MeterDefinitionException( _LE("Invalid type %s specified") % self.cfg['type'], self.cfg) self._fallback_user_id = declarative.Definition( @@ -193,10 +185,9 @@ class ProcessMeterNotifications(plugin_base.NotificationBase): or not cfg.CONF.notification.disable_non_metric_meters): try: md = MeterDefinition(meter_cfg, plugin_manager) - except declarative.DefinitionException as me: - errmsg = (_LE("Error loading meter definition : %(err)s") - % dict(err=six.text_type(me))) - LOG.error(errmsg) + except declarative.DefinitionException as e: + errmsg = _LE("Error loading meter definition: %s") + LOG.error(errmsg, six.text_type(e)) else: definitions[meter_cfg['name']] = md return definitions.values() diff --git a/ceilometer/tests/unit/hardware/pollsters/test_generic.py b/ceilometer/tests/unit/hardware/pollsters/test_generic.py index 480e481f5b..35d3172757 100644 --- a/ceilometer/tests/unit/hardware/pollsters/test_generic.py +++ b/ceilometer/tests/unit/hardware/pollsters/test_generic.py @@ -44,8 +44,8 @@ class TestMeterDefinition(test_base.BaseTestCase): cfg = dict(name='test', type='gauge') try: generic.MeterDefinition(cfg) - except generic.MeterDefinitionException as e: - self.assertEqual("Missing field unit", e.message) + except declarative.MeterDefinitionException as e: + self.assertEqual("Missing field unit", e.brief_message) def test_config_invalid_field(self): cfg = dict(name='test', @@ -62,8 +62,9 @@ class TestMeterDefinition(test_base.BaseTestCase): snmp_inspector={}) try: generic.MeterDefinition(cfg) - except generic.MeterDefinitionException as e: - self.assertEqual("Unrecognized type value invalid", e.message) + except declarative.MeterDefinitionException as e: + self.assertEqual("Unrecognized type value invalid", + e.brief_message) @mock.patch('ceilometer.hardware.pollsters.generic.LOG') def test_bad_metric_skip(self, LOG): @@ -82,7 +83,7 @@ class TestMeterDefinition(test_base.BaseTestCase): data = generic.load_definition(cfg) self.assertEqual(2, len(data)) LOG.error.assert_called_with( - "Error loading meter definition : " + "Error loading meter definition: %s", "Unrecognized type value invalid") diff --git a/ceilometer/tests/unit/meter/test_notifications.py b/ceilometer/tests/unit/meter/test_notifications.py index 6b1bfcdd44..7da56432b2 100644 --- a/ceilometer/tests/unit/meter/test_notifications.py +++ b/ceilometer/tests/unit/meter/test_notifications.py @@ -242,10 +242,10 @@ class TestMeterDefinition(test.BaseTestCase): try: notifications.MeterDefinition(cfg, mock.Mock()) except declarative.DefinitionException as e: - self.assertEqual("Required fields ['name', 'type', 'event_type'," - " 'unit', 'volume', 'resource_id']" - " not specified", - encodeutils.exception_to_unicode(e)) + self.assertIn("Required fields ['name', 'type', 'event_type'," + " 'unit', 'volume', 'resource_id']" + " not specified", + encodeutils.exception_to_unicode(e)) def test_bad_type_cfg_definition(self): cfg = dict(name="test", type="foo", event_type="bar.create", @@ -254,8 +254,8 @@ class TestMeterDefinition(test.BaseTestCase): try: notifications.MeterDefinition(cfg, mock.Mock()) except declarative.DefinitionException as e: - self.assertEqual("Invalid type foo specified", - encodeutils.exception_to_unicode(e)) + self.assertIn("Invalid type foo specified", + encodeutils.exception_to_unicode(e)) class TestMeterProcessing(test.BaseTestCase): @@ -312,9 +312,9 @@ class TestMeterProcessing(test.BaseTestCase): project_id="$.payload.project_id")]}) self._load_meter_def_file(cfg) self.assertEqual(2, len(self.handler.definitions)) - LOG.error.assert_called_with( - "Error loading meter definition : " - "Invalid type bad_type specified") + args, kwargs = LOG.error.call_args_list[0] + self.assertEqual("Error loading meter definition: %s", args[0]) + self.assertTrue(args[1].endswith("Invalid type bad_type specified")) def test_jsonpath_values_parsed(self): cfg = yaml.dump(