diff --git a/ceilometer/agent/plugin_base.py b/ceilometer/agent/plugin_base.py index 3cae66ccc7..5083c87c8e 100644 --- a/ceilometer/agent/plugin_base.py +++ b/ceilometer/agent/plugin_base.py @@ -93,7 +93,7 @@ class NotificationBase(PluginBase): super(NotificationBase, self).__init__() # NOTE(gordc): this is filter rule used by oslo.messaging to dispatch # messages to an endpoint. - if self.event_types is not None: + if self.event_types: self.filter_rule = oslo_messaging.NotificationFilter( event_type='|'.join(self.event_types)) self.manager = manager diff --git a/ceilometer/exchange_control.py b/ceilometer/exchange_control.py new file mode 100644 index 0000000000..6a9b130f50 --- /dev/null +++ b/ceilometer/exchange_control.py @@ -0,0 +1,26 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_config import cfg + +EXCHANGE_OPTS = [ + cfg.StrOpt('heat_control_exchange', + default='heat', + help="Exchange name for Heat notifications"), + cfg.StrOpt('glance_control_exchange', + default='glance', + help="Exchange name for Glance notifications."), + cfg.StrOpt('magnetodb_control_exchange', + default='magnetodb', + help="Exchange name for Magnetodb notifications."), +] diff --git a/ceilometer/image/notifications.py b/ceilometer/image/notifications.py deleted file mode 100644 index 03ac5299f3..0000000000 --- a/ceilometer/image/notifications.py +++ /dev/null @@ -1,126 +0,0 @@ -# -# Copyright 2012 Red Hat, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Handler for producing image metering messages from glance notification - events. -""" - -from oslo_config import cfg -import oslo_messaging - -from ceilometer.agent import plugin_base -from ceilometer import sample - -OPTS = [ - cfg.StrOpt('glance_control_exchange', - default='glance', - help="Exchange name for Glance notifications."), -] - - -cfg.CONF.register_opts(OPTS) - - -class ImageBase(plugin_base.NotificationBase): - """Base class for image counting.""" - - @staticmethod - def get_targets(conf): - """Return a sequence of oslo_messaging.Target - - This sequence is defining the exchange and topics to be connected for - this plugin. - """ - return [oslo_messaging.Target(topic=topic, - exchange=conf.glance_control_exchange) - for topic in conf.notification_topics] - - -class ImageCRUDBase(ImageBase): - event_types = [ - 'image.update', - 'image.upload', - 'image.delete', - ] - - -class ImageCRUD(ImageCRUDBase, plugin_base.NonMetricNotificationBase): - def process_notification(self, message): - yield sample.Sample.from_notification( - name=message['event_type'], - type=sample.TYPE_DELTA, - unit='image', - volume=1, - resource_id=message['payload']['id'], - user_id=None, - project_id=message['payload']['owner'], - message=message) - - -class Image(ImageCRUDBase, plugin_base.NonMetricNotificationBase): - def process_notification(self, message): - yield sample.Sample.from_notification( - name='image', - type=sample.TYPE_GAUGE, - unit='image', - volume=1, - resource_id=message['payload']['id'], - user_id=None, - project_id=message['payload']['owner'], - message=message) - - -class ImageSize(ImageCRUDBase): - def process_notification(self, message): - yield sample.Sample.from_notification( - name='image.size', - type=sample.TYPE_GAUGE, - unit='B', - volume=message['payload']['size'], - resource_id=message['payload']['id'], - user_id=None, - project_id=message['payload']['owner'], - message=message) - - -class ImageDownload(ImageBase): - """Emit image_download sample when an image is downloaded.""" - event_types = ['image.send'] - - def process_notification(self, message): - yield sample.Sample.from_notification( - name='image.download', - type=sample.TYPE_DELTA, - unit='B', - volume=message['payload']['bytes_sent'], - resource_id=message['payload']['image_id'], - user_id=message['payload']['receiver_user_id'], - project_id=message['payload']['receiver_tenant_id'], - message=message) - - -class ImageServe(ImageBase): - """Emit image_serve sample when an image is served out.""" - event_types = ['image.send'] - - def process_notification(self, message): - yield sample.Sample.from_notification( - name='image.serve', - type=sample.TYPE_DELTA, - unit='B', - volume=message['payload']['bytes_sent'], - resource_id=message['payload']['image_id'], - user_id=None, - project_id=message['payload']['owner_id'], - message=message) diff --git a/ceilometer/key_value_storage/__init__.py b/ceilometer/key_value_storage/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ceilometer/key_value_storage/notifications.py b/ceilometer/key_value_storage/notifications.py deleted file mode 100644 index 1a9e85c0fe..0000000000 --- a/ceilometer/key_value_storage/notifications.py +++ /dev/null @@ -1,79 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg -import oslo_messaging - -from ceilometer.agent import plugin_base -from ceilometer import sample - -OPTS = [ - cfg.StrOpt('magnetodb_control_exchange', - default='magnetodb', - help="Exchange name for Magnetodb notifications."), -] - - -cfg.CONF.register_opts(OPTS) - - -class _Base(plugin_base.NotificationBase): - """Convert magnetodb notification into Samples.""" - - @staticmethod - def get_targets(conf): - """Return a sequence of oslo_messaging.Target - - Sequence defining the exchange and topics to be connected for this - plugin. - """ - return [oslo_messaging.Target(topic=topic, - exchange=conf.magnetodb_control_exchange) - for topic in conf.notification_topics] - - -class Table(_Base, plugin_base.NonMetricNotificationBase): - - event_types = [ - 'magnetodb.table.create.end', - 'magnetodb.table.delete.end' - ] - - def process_notification(self, message): - meter_name = '.'.join(message['event_type'].split('.')[:-1]) - yield sample.Sample.from_notification( - name=meter_name, - type=sample.TYPE_GAUGE, - unit='table', - volume=1, - resource_id=message['payload']['table_uuid'], - user_id=message['_context_user'], - project_id=message['_context_tenant'], - message=message) - - -class Index(_Base): - - event_types = [ - 'magnetodb.table.create.end' - ] - - def process_notification(self, message): - yield sample.Sample.from_notification( - name='magnetodb.table.index.count', - type=sample.TYPE_GAUGE, - unit='index', - volume=message['payload']['index_count'], - resource_id=message['payload']['table_uuid'], - user_id=message['_context_user'], - project_id=message['_context_tenant'], - message=message) diff --git a/ceilometer/meter/data/meters.yaml b/ceilometer/meter/data/meters.yaml new file mode 100644 index 0000000000..4abda0795b --- /dev/null +++ b/ceilometer/meter/data/meters.yaml @@ -0,0 +1,126 @@ +--- + +metric: + # Image + - name: "image.size" + event_type: + - "image.upload" + - "image.delete" + - "image.update" + type: "gauge" + unit: B + volume: payload.size + resource_id: payload.id + project_id: payload.owner + + - name: "image.download" + event_type: "image.send" + type: "delta" + unit: "B" + volume: payload.bytes_sent + resource_id: payload.image_id + user_id: payload.receiver_user_id + project_id: payload.receiver_tenant_id + + - name: "image.serve" + event_type: "image.send" + type: "delta" + unit: "B" + volume: payload.bytes_sent + resource_id: payload.image_id + project_id: payload.owner_id + + # MagnetoDB + - name: 'magnetodb.table.index.count' + type: 'gauge' + unit: 'index' + event_type: 'magnetodb.table.create.end' + volume: payload.index_count + resource_id: payload.table_uuid + user_id: _context_user + + +# NOTE: non-metric meters are generally events/existence meters +# These are expected to be DEPRECATED in future releases +# + # Image + - name: "image" + event_type: + - "image.upload" + - "image.delete" + - "image.update" + type: "gauge" + unit: 'image' + volume: 1 + resource_id: payload.id + project_id: payload.owner + + # Orchestration + - name: 'stack.create' + event_type: + - 'orchestration.stack.create.end' + type: 'delta' + unit: 'stack' + volume: 1 + user_id: _context_trustor_user_id + project_id: payload.tenant_id + resource_id: payload.stack_identity + + - name: 'stack.update' + event_type: + - 'orchestration.stack.update.end' + type: 'delta' + unit: 'stack' + volume: 1 + user_id: _context_trustor_user_id + project_id: payload.tenant_id + resource_id: payload.stack_identity + + - name: 'stack.delete' + event_type: + - 'orchestration.stack.delete.end' + type: 'delta' + unit: 'stack' + volume: 1 + user_id: _context_trustor_user_id + project_id: payload.tenant_id + resource_id: payload.stack_identity + + - name: 'stack.resume' + event_type: + - 'orchestration.stack.resume.end' + type: 'delta' + unit: 'stack' + volume: 1 + user_id: _context_trustor_user_id + project_id: payload.tenant_id + resource_id: payload.stack_identity + + - name: 'stack.suspend' + event_type: + - 'orchestration.stack.suspend.end' + type: 'delta' + unit: 'stack' + volume: 1 + user_id: _context_trustor_user_id + project_id: payload.tenant_id + resource_id: payload.stack_identity + + # MagnetoDB + - name: 'magnetodb.table.create' + type: 'gauge' + unit: 'table' + volume: 1 + event_type: 'magnetodb.table.create.end' + resource_id: payload.table_uuid + user_id: _context_user + project_id: _context_tenant + + - name: 'magnetodb.table.delete' + type: 'gauge' + unit: 'table' + volume: 1 + event_type: 'magnetodb.table.delete.end' + resource_id: payload.table_uuid + user_id: _context_user + project_id: _context_tenant diff --git a/ceilometer/meter/notifications.py b/ceilometer/meter/notifications.py index f1062bbb4e..61b386def2 100644 --- a/ceilometer/meter/notifications.py +++ b/ceilometer/meter/notifications.py @@ -13,6 +13,7 @@ import fnmatch import os +import pkg_resources import six import yaml @@ -95,6 +96,9 @@ def get_config_file(): config_file = cfg.CONF.meter.meter_definitions_cfg_file if not os.path.exists(config_file): config_file = cfg.CONF.find_file(config_file) + if not config_file: + config_file = pkg_resources.resource_filename( + __name__, "data/meters.yaml") return config_file @@ -127,7 +131,7 @@ def setup_meters_config(): else: LOG.debug(_LE("No Meter Definitions configuration file found!" " Using default config.")) - meters_config = [] + meters_config = {} LOG.info(_LE("Meter Definitions: %s"), meters_config) @@ -135,13 +139,15 @@ def setup_meters_config(): def load_definitions(config_def): + if not config_def: + return [] return [MeterDefinition(event_def) for event_def in reversed(config_def['metric'])] class ProcessMeterNotifications(plugin_base.NotificationBase): - event_types = None + event_types = [] def __init__(self, manager): super(ProcessMeterNotifications, self).__init__(manager) diff --git a/ceilometer/middleware.py b/ceilometer/middleware.py index 4cafe3cda2..0cb1eebe41 100644 --- a/ceilometer/middleware.py +++ b/ceilometer/middleware.py @@ -22,7 +22,7 @@ from ceilometer import sample cfg.CONF.import_opt('nova_control_exchange', 'ceilometer.compute.notifications') cfg.CONF.import_opt('glance_control_exchange', - 'ceilometer.image.notifications') + 'ceilometer.notification') cfg.CONF.import_opt('neutron_control_exchange', 'ceilometer.network.notifications') cfg.CONF.import_opt('cinder_control_exchange', diff --git a/ceilometer/notification.py b/ceilometer/notification.py index 3965b09cca..e41a3af50a 100644 --- a/ceilometer/notification.py +++ b/ceilometer/notification.py @@ -23,6 +23,7 @@ from ceilometer.agent import plugin_base as base from ceilometer import coordination from ceilometer.event import endpoint as event_endpoint from ceilometer.i18n import _, _LI, _LW +from ceilometer import exchange_control from ceilometer import messaging from ceilometer import pipeline from ceilometer import service_base @@ -60,6 +61,7 @@ OPTS = [ "(DEFAULT/transport_url is used if empty)"), ] +cfg.CONF.register_opts(exchange_control.EXCHANGE_OPTS) cfg.CONF.register_opts(OPTS, group="notification") cfg.CONF.import_opt('telemetry_driver', 'ceilometer.publisher.messaging', group='publisher_notifier') diff --git a/ceilometer/opts.py b/ceilometer/opts.py index 1e1bf582e3..77c5ef800f 100644 --- a/ceilometer/opts.py +++ b/ceilometer/opts.py @@ -38,7 +38,6 @@ import ceilometer.event.converter import ceilometer.hardware.discovery import ceilometer.identity.notifications import ceilometer.image.glance -import ceilometer.image.notifications import ceilometer.ipmi.notifications.ironic import ceilometer.ipmi.platform.intel_node_manager import ceilometer.ipmi.pollsters @@ -49,7 +48,6 @@ import ceilometer.notification import ceilometer.nova_client import ceilometer.objectstore.rgw import ceilometer.objectstore.swift -import ceilometer.orchestration.notifications import ceilometer.pipeline import ceilometer.profiler.notifications import ceilometer.publisher.messaging @@ -75,13 +73,11 @@ def list_opts(): ceilometer.dispatcher.OPTS, ceilometer.identity.notifications.OPTS, ceilometer.image.glance.OPTS, - ceilometer.image.notifications.OPTS, ceilometer.ipmi.notifications.ironic.OPTS, ceilometer.middleware.OPTS, ceilometer.network.notifications.OPTS, ceilometer.nova_client.OPTS, ceilometer.objectstore.swift.OPTS, - ceilometer.orchestration.notifications.OPTS, ceilometer.pipeline.OPTS, ceilometer.profiler.notifications.OPTS, ceilometer.sample.OPTS, diff --git a/ceilometer/orchestration/__init__.py b/ceilometer/orchestration/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ceilometer/orchestration/notifications.py b/ceilometer/orchestration/notifications.py deleted file mode 100644 index dd2be3773e..0000000000 --- a/ceilometer/orchestration/notifications.py +++ /dev/null @@ -1,76 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Handler for producing orchestration metering from Heat notification - events. -""" - -from oslo_config import cfg -import oslo_messaging - -from ceilometer.agent import plugin_base -from ceilometer import sample - - -OPTS = [ - cfg.StrOpt('heat_control_exchange', - default='heat', - help="Exchange name for Heat notifications"), -] - -cfg.CONF.register_opts(OPTS) -SERVICE = 'orchestration' - - -class StackCRUD(plugin_base.NotificationBase, - plugin_base.NonMetricNotificationBase): - - resource_name = '%s.stack' % SERVICE - - @property - def event_types(self): - return [ - '%s.create.end' % self.resource_name, - '%s.update.end' % self.resource_name, - '%s.delete.end' % self.resource_name, - '%s.resume.end' % self.resource_name, - '%s.suspend.end' % self.resource_name, - ] - - @staticmethod - def get_targets(conf): - """Return a sequence of oslo_messaging.Target - - It is defining the exchange and topics to be connected for this plugin. - """ - return [oslo_messaging.Target(topic=topic, - exchange=conf.heat_control_exchange) - for topic in conf.notification_topics] - - def process_notification(self, message): - name = (message['event_type'].replace(self.resource_name, 'stack') - .replace('.end', '')) - - project_id = message['payload']['tenant_id'] - - # Trying to use the trustor_id if trusts is used by Heat, - user_id = (message.get('_context_trustor_user_id') or - message['_context_user_id']) - - yield sample.Sample.from_notification( - name=name, - type=sample.TYPE_DELTA, - unit='stack', - volume=1, - resource_id=message['payload']['stack_identity'], - user_id=user_id, - project_id=project_id, - message=message) diff --git a/ceilometer/tests/functional/test_notification.py b/ceilometer/tests/functional/test_notification.py index 05b5d8cfdd..5fe14fa211 100644 --- a/ceilometer/tests/functional/test_notification.py +++ b/ceilometer/tests/functional/test_notification.py @@ -33,6 +33,7 @@ from ceilometer.compute.notifications import instance from ceilometer import messaging from ceilometer import notification from ceilometer.publisher import test as test_publisher +from ceilometer import service from ceilometer.tests import base as tests_base TEST_NOTICE_CTXT = { @@ -198,6 +199,7 @@ class BaseRealNotification(tests_base.BaseTestCase): def setUp(self): super(BaseRealNotification, self).setUp() self.CONF = self.useFixture(fixture_config.Config()).conf + service.prepare_service([]) self.setup_messaging(self.CONF, 'nova') pipeline_cfg_file = self.setup_pipeline(['instance', 'memory']) diff --git a/ceilometer/tests/unit/image/test_notifications.py b/ceilometer/tests/unit/image/test_notifications.py deleted file mode 100644 index 2e0d723d57..0000000000 --- a/ceilometer/tests/unit/image/test_notifications.py +++ /dev/null @@ -1,197 +0,0 @@ -# -# Copyright 2012 Red Hat Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -import mock -from oslotest import base - -from ceilometer.image import notifications -from ceilometer import sample - - -def fake_uuid(x): - return '%s-%s-%s-%s' % (x * 8, x * 4, x * 4, x * 12) - - -NOW = datetime.datetime.isoformat(datetime.datetime.utcnow()) - -NOTIFICATION_SEND = { - u'event_type': u'image.send', - u'timestamp': NOW, - u'message_id': fake_uuid('a'), - u'priority': u'INFO', - u'publisher_id': u'images.example.com', - u'payload': {u'receiver_tenant_id': fake_uuid('b'), - u'destination_ip': u'1.2.3.4', - u'bytes_sent': 42, - u'image_id': fake_uuid('c'), - u'receiver_user_id': fake_uuid('d'), - u'owner_id': fake_uuid('e')} -} - -IMAGE_META = {u'status': u'saving', - u'name': u'fake image #3', - u'deleted': False, - u'container_format': u'ovf', - u'created_at': u'2012-09-18T10:13:44.571370', - u'disk_format': u'vhd', - u'updated_at': u'2012-09-18T10:13:44.623120', - u'properties': {u'key2': u'value2', - u'key1': u'value1'}, - u'min_disk': 0, - u'protected': False, - u'id': fake_uuid('c'), - u'location': None, - u'checksum': u'd990432ef91afef3ad9dbf4a975d3365', - u'owner': "fake", - u'is_public': False, - u'deleted_at': None, - u'min_ram': 0, - u'size': 19} - - -NOTIFICATION_UPDATE = {"message_id": "0c65cb9c-018c-11e2-bc91-5453ed1bbb5f", - "publisher_id": "images.example.com", - "event_type": "image.update", - "priority": "info", - "payload": IMAGE_META, - "timestamp": NOW} - - -NOTIFICATION_UPLOAD = {"message_id": "0c65cb9c-018c-11e2-bc91-5453ed1bbb5f", - "publisher_id": "images.example.com", - "event_type": "image.upload", - "priority": "info", - "payload": IMAGE_META, - "timestamp": NOW} - - -NOTIFICATION_DELETE = {"message_id": "0c65cb9c-018c-11e2-bc91-5453ed1bbb5f", - "publisher_id": "images.example.com", - "event_type": "image.delete", - "priority": "info", - "payload": IMAGE_META, - "timestamp": NOW} - - -class TestNotification(base.BaseTestCase): - - def _verify_common_counter(self, c, name, volume): - self.assertIsNotNone(c) - self.assertEqual(name, c.name) - self.assertEqual(fake_uuid('c'), c.resource_id) - self.assertEqual(NOW, c.timestamp) - self.assertEqual(volume, c.volume) - metadata = c.resource_metadata - self.assertEqual(u'images.example.com', metadata.get('host')) - - def test_image_download(self): - handler = notifications.ImageDownload(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_SEND)) - self.assertEqual(1, len(counters)) - download = counters[0] - self._verify_common_counter(download, 'image.download', 42) - self.assertEqual(fake_uuid('d'), download.user_id) - self.assertEqual(fake_uuid('b'), download.project_id) - self.assertEqual(sample.TYPE_DELTA, download.type) - - def test_image_serve(self): - handler = notifications.ImageServe(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_SEND)) - self.assertEqual(1, len(counters)) - serve = counters[0] - self._verify_common_counter(serve, 'image.serve', 42) - self.assertEqual(fake_uuid('e'), serve.project_id) - self.assertEqual(fake_uuid('d'), - serve.resource_metadata.get('receiver_user_id')) - self.assertEqual(fake_uuid('b'), - serve.resource_metadata.get('receiver_tenant_id')) - self.assertEqual(sample.TYPE_DELTA, serve.type) - - def test_image_crud_on_update(self): - handler = notifications.ImageCRUD(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_UPDATE)) - self.assertEqual(1, len(counters)) - update = counters[0] - self._verify_common_counter(update, 'image.update', 1) - self.assertEqual(sample.TYPE_DELTA, update.type) - - def test_image_on_update(self): - handler = notifications.Image(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_UPDATE)) - self.assertEqual(1, len(counters)) - update = counters[0] - self._verify_common_counter(update, 'image', 1) - self.assertEqual(sample.TYPE_GAUGE, update.type) - - def test_image_size_on_update(self): - handler = notifications.ImageSize(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_UPDATE)) - self.assertEqual(1, len(counters)) - update = counters[0] - self._verify_common_counter(update, 'image.size', - IMAGE_META['size']) - self.assertEqual(sample.TYPE_GAUGE, update.type) - - def test_image_crud_on_upload(self): - handler = notifications.ImageCRUD(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_UPLOAD)) - self.assertEqual(1, len(counters)) - upload = counters[0] - self._verify_common_counter(upload, 'image.upload', 1) - self.assertEqual(sample.TYPE_DELTA, upload.type) - - def test_image_on_upload(self): - handler = notifications.Image(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_UPLOAD)) - self.assertEqual(1, len(counters)) - upload = counters[0] - self._verify_common_counter(upload, 'image', 1) - self.assertEqual(sample.TYPE_GAUGE, upload.type) - - def test_image_size_on_upload(self): - handler = notifications.ImageSize(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_UPLOAD)) - self.assertEqual(1, len(counters)) - upload = counters[0] - self._verify_common_counter(upload, 'image.size', - IMAGE_META['size']) - self.assertEqual(sample.TYPE_GAUGE, upload.type) - - def test_image_crud_on_delete(self): - handler = notifications.ImageCRUD(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_DELETE)) - self.assertEqual(1, len(counters)) - delete = counters[0] - self._verify_common_counter(delete, 'image.delete', 1) - self.assertEqual(sample.TYPE_DELTA, delete.type) - - def test_image_on_delete(self): - handler = notifications.Image(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_DELETE)) - self.assertEqual(1, len(counters)) - delete = counters[0] - self._verify_common_counter(delete, 'image', 1) - self.assertEqual(sample.TYPE_GAUGE, delete.type) - - def test_image_size_on_delete(self): - handler = notifications.ImageSize(mock.Mock()) - counters = list(handler.process_notification(NOTIFICATION_DELETE)) - self.assertEqual(1, len(counters)) - delete = counters[0] - self._verify_common_counter(delete, 'image.size', - IMAGE_META['size']) - self.assertEqual(sample.TYPE_GAUGE, delete.type) diff --git a/ceilometer/tests/unit/key_value_storage/test_notifications.py b/ceilometer/tests/unit/key_value_storage/test_notifications.py deleted file mode 100644 index 1731c2689e..0000000000 --- a/ceilometer/tests/unit/key_value_storage/test_notifications.py +++ /dev/null @@ -1,124 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -import mock - -from oslo_config import fixture as fixture_config - -from ceilometer.meter import notifications -from ceilometer import sample -from ceilometer.tests import base as test - - -def fake_uuid(x): - return '%s-%s-%s-%s' % (x * 8, x * 4, x * 4, x * 12) - - -NOW = datetime.datetime.isoformat(datetime.datetime.utcnow()) - - -TABLE_CREATE_PAYLOAD = { - u'table_uuid': fake_uuid('r'), - u'index_count': 2, - u'table_name': u'email_data' - } - -TABLE_DELETE_PAYLOAD = { - u'table_uuid': fake_uuid('r'), - u'table_name': u'email_data' - } - -NOTIFICATION_TABLE_CREATE = { - u'_context_request_id': u'req-d6e9b7ec-976f-443f-ba6e-e2b89b18aa75', - u'_context_tenant': fake_uuid('t'), - u'_context_user': fake_uuid('u'), - u'_context_auth_token': u'', - u'_context_show_deleted': False, - u'_context_is_admin': u'False', - u'_context_read_only': False, - 'payload': TABLE_CREATE_PAYLOAD, - 'publisher_id': u'magnetodb.winterfell.com', - 'message_id': u'3d71fb8a-f1d7-4a4e-b29f-7a711a761ba1', - 'event_type': u'magnetodb.table.create.end', - 'timestamp': NOW, - 'priority': 'info' - } - -NOTIFICATION_TABLE_DELETE = { - u'_context_request_id': u'req-d6e9b7ec-976f-443f-ba6e-e2b89b18aa75', - u'_context_tenant': fake_uuid('t'), - u'_context_user': fake_uuid('u'), - u'_context_auth_token': u'', - u'_context_show_deleted': False, - u'_context_is_admin': u'False', - u'_context_read_only': False, - 'payload': TABLE_DELETE_PAYLOAD, - 'publisher_id': u'magnetodb.winterfell.com', - 'message_id': u'4c8f5940-3c90-41af-ac16-f0e3055a305d', - 'event_type': u'magnetodb.table.delete.end', - 'timestamp': NOW, - 'priority': 'info' - } - - -class TestNotification(test.BaseTestCase): - - def setUp(self): - super(TestNotification, self).setUp() - self.CONF = self.useFixture(fixture_config.Config()).conf - self.CONF.set_override( - 'meter_definitions_cfg_file', - self.path_get('etc/ceilometer/meters.yaml'), group='meter') - self.handler = notifications.ProcessMeterNotifications(mock.Mock()) - - def _verify_common_counter(self, c, name, volume): - self.assertIsNotNone(c) - self.assertEqual(name, c.name) - self.assertEqual(fake_uuid('r'), c.resource_id) - self.assertEqual(NOW, c.timestamp) - self.assertEqual(volume, c.volume) - metadata = c.resource_metadata - self.assertEqual(u'magnetodb.winterfell.com', metadata.get('host')) - - def test_create_table(self): - counters = list(self.handler.process_notification( - NOTIFICATION_TABLE_CREATE)) - self.assertEqual(2, len(counters)) - table = [item for item in counters - if item.name == "magnetodb.table.create"][0] - self._verify_common_counter(table, 'magnetodb.table.create', 1) - self.assertEqual(fake_uuid('u'), table.user_id) - self.assertEqual(fake_uuid('t'), table.project_id) - self.assertEqual(sample.TYPE_GAUGE, table.type) - - def test_delete_table(self): - counters = list(self.handler.process_notification( - NOTIFICATION_TABLE_DELETE)) - self.assertEqual(1, len(counters)) - table = counters[0] - self._verify_common_counter(table, 'magnetodb.table.delete', 1) - self.assertEqual(fake_uuid('u'), table.user_id) - self.assertEqual(fake_uuid('t'), table.project_id) - self.assertEqual(sample.TYPE_GAUGE, table.type) - - def test_index_count(self): - counters = list(self.handler.process_notification( - NOTIFICATION_TABLE_CREATE)) - self.assertEqual(2, len(counters)) - table = [item for item in counters - if item.name == "magnetodb.table.index.count"][0] - self._verify_common_counter(table, 'magnetodb.table.index.count', 2) - self.assertEqual(fake_uuid('u'), table.user_id) - self.assertEqual(fake_uuid('t'), table.project_id) - self.assertEqual(sample.TYPE_GAUGE, table.type) diff --git a/ceilometer/tests/unit/meter/test_notifications.py b/ceilometer/tests/unit/meter/test_notifications.py index bffef64122..d5d85acd9f 100644 --- a/ceilometer/tests/unit/meter/test_notifications.py +++ b/ceilometer/tests/unit/meter/test_notifications.py @@ -20,6 +20,7 @@ from oslo_config import fixture as fixture_config from oslo_utils import fileutils from ceilometer.meter import notifications +from ceilometer import service as ceilometer_service from ceilometer.tests import base as test NOTIFICATION = { @@ -82,11 +83,13 @@ class TestMeterProcessing(test.BaseTestCase): def setUp(self): super(TestMeterProcessing, self).setUp() self.CONF = self.useFixture(fixture_config.Config()).conf - self.CONF.set_override( - 'meter_definitions_cfg_file', - self.path_get('etc/ceilometer/meters.yaml'), group='meter') + ceilometer_service.prepare_service([]) self.handler = notifications.ProcessMeterNotifications(mock.Mock()) + def test_fallback_meter_path(self): + fall_bak_path = notifications.get_config_file() + self.assertIn("meter/data/meters.yaml", fall_bak_path) + def __setup_meter_def_file(self, cfg): if six.PY3: cfg = cfg.encode('utf-8') diff --git a/ceilometer/tests/unit/orchestration/test_notifications.py b/ceilometer/tests/unit/orchestration/test_notifications.py deleted file mode 100644 index f222354540..0000000000 --- a/ceilometer/tests/unit/orchestration/test_notifications.py +++ /dev/null @@ -1,138 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -import mock -from oslo_config import cfg -from oslo_config import fixture as fixture_config -from oslo_log import log - -from ceilometer.meter import notifications -from ceilometer import sample -from ceilometer.tests import base as test - -NOW = datetime.datetime.isoformat(datetime.datetime.utcnow()) - -TENANT_ID = u'4c35985848bf4419b3f3d52c22e5792d' -STACK_NAME = u'AS1-ASGroup-53sqbo7sor7i' -STACK_ID = u'cb4a6fd1-1f5d-4002-ae91-9b91573cfb03' -USER_NAME = u'demo' -USER_ID = u'2e61f25ec63a4f6c954a6245421448a4' -TRUSTOR_ID = u'foo-Trustor-Id' - -STACK_ARN = u'arn:openstack:heat::%s:stacks/%s/%s' % (TENANT_ID, - STACK_NAME, - STACK_ID) - - -CONF = cfg.CONF -log.register_options(CONF) -CONF.set_override('use_stderr', True) - -LOG = log.getLogger(__name__) - - -def stack_notification_for(operation, use_trust=None): - - if use_trust: - trust_id = 'footrust' - trustor_id = TRUSTOR_ID - else: - trust_id = None - trustor_id = None - - return { - u'event_type': 'orchestration.stack.%s.end' % operation, - u'_context_roles': [ - u'Member', - ], - u'_context_request_id': u'req-cf24cf30-af35-4a47-ae29-e74d75ebc6de', - u'_context_auth_url': u'http://0.1.0.1:1010/v2.0', - u'timestamp': NOW, - u'_unique_id': u'1afb4283660f410c802af4d5992a39f2', - u'_context_tenant_id': TENANT_ID, - u'payload': { - u'state_reason': u'Stack create completed successfully', - u'user_id': USER_NAME, - u'stack_identity': STACK_ARN, - u'stack_name': STACK_NAME, - u'tenant_id': TENANT_ID, - u'create_at': u'2014-01-27T13:13:19Z', - u'state': u'CREATE_COMPLETE' - }, - u'_context_username': USER_NAME, - u'_context_auth_token': u'MIISAwYJKoZIhvcNAQcCoII...', - u'_context_password': u'password', - u'_context_user_id': USER_ID, - u'_context_trustor_user_id': trustor_id, - u'_context_aws_creds': None, - u'_context_show_deleted': False, - u'_context_tenant': USER_NAME, - u'_context_trust_id': trust_id, - u'priority': u'INFO', - u'_context_is_admin': False, - u'_context_user': USER_NAME, - u'publisher_id': u'orchestration.node-n5x66lxdy67d', - u'message_id': u'ef921faa-7f7b-4854-8b86-a424ab93c96e', - } - - -class TestNotification(test.BaseTestCase): - - def setUp(self): - super(TestNotification, self).setUp() - self.CONF = self.useFixture(fixture_config.Config()).conf - self.CONF.set_override( - 'meter_definitions_cfg_file', - self.path_get('etc/ceilometer/meters.yaml'), group='meter') - self.handler = notifications.ProcessMeterNotifications(mock.Mock()) - - def _verify_common_sample(self, s, name, volume): - self.assertIsNotNone(s) - self.assertEqual('stack.%s' % name, s.name) - self.assertEqual(NOW, s.timestamp) - self.assertEqual(sample.TYPE_DELTA, s.type) - self.assertEqual(TENANT_ID, s.project_id) - self.assertEqual(STACK_ARN, s.resource_id) - metadata = s.resource_metadata - self.assertEqual(u'orchestration.node-n5x66lxdy67d', - metadata.get('host')) - - def _test_operation(self, operation, trust=None): - notif = stack_notification_for(operation, trust) - - data = list(self.handler.process_notification(notif)) - self.assertEqual(1, len(data)) - if trust: - self.assertEqual(TRUSTOR_ID, data[0].user_id) - else: - self.assertEqual(USER_ID, data[0].user_id) - self._verify_common_sample(data[0], operation, 1) - - def test_create(self): - self._test_operation('create') - - def test_create_trust(self): - self._test_operation('create', trust=True) - - def test_update(self): - self._test_operation('update') - - def test_delete(self): - self._test_operation('delete') - - def test_resume(self): - self._test_operation('resume') - - def test_suspend(self): - self._test_operation('suspend') diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 44c727ce4e..614f87c86f 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -256,6 +256,7 @@ function configure_ceilometer { cp $CEILOMETER_DIR/etc/ceilometer/event_definitions.yaml $CEILOMETER_CONF_DIR cp $CEILOMETER_DIR/etc/ceilometer/gnocchi_archive_policy_map.yaml $CEILOMETER_CONF_DIR cp $CEILOMETER_DIR/etc/ceilometer/gnocchi_resources.yaml $CEILOMETER_CONF_DIR + cp $CEILOMETER_DIR/ceilometer/meter/data/meters.yaml $CEILOMETER_CONF_DIR if [ "$CEILOMETER_PIPELINE_INTERVAL" ]; then sed -i "s/interval:.*/interval: ${CEILOMETER_PIPELINE_INTERVAL}/" $CEILOMETER_CONF_DIR/pipeline.yaml diff --git a/etc/ceilometer/meters.yaml b/etc/ceilometer/meters.yaml deleted file mode 100644 index 320cdb9c85..0000000000 --- a/etc/ceilometer/meters.yaml +++ /dev/null @@ -1,393 +0,0 @@ ---- - -metric: - - name: "image.size" - event_type: - - "image.upload" - - "image.delete" - - "image.update" - type: "gauge" - unit: B - volume: payload.size - resource_id: payload.id - project_id: payload.owner - - - name: "image.download" - event_type: "image.send" - type: "delta" - unit: "B" - volume: payload.bytes_sent - resource_id: payload.image_id - user_id: payload.receiver_user_id - project_id: payload.receiver_tenant_id - - - name: "image.serve" - event_type: "image.send" - type: "delta" - unit: "B" - volume: payload.bytes_sent - resource_id: payload.image_id - project_id: payload.owner_id - - - name: 'bandwidth' - event_type: 'l3.meter' - type: 'delta' - unit: 'B' - volume: payload.bytes - project_id: payload.tenant_id - resource_id: payload.label_id - - - name: 'magnetodb.table.index.count' - type: 'gauge' - unit: 'index' - event_type: 'magnetodb.table.create.end' - volume: payload.index_count - resource_id: payload.table_uuid - user_id: _context_user - - - name: 'memory' - event_type: 'compute.instance.*' - type: 'gauge' - unit: 'MB' - volume: payload.memory_mb - user_id: payload.user_id - project_id: payload.tenant_id - resource_id: payload.instance_id - - - name: 'vcpus' - event_type: 'compute.instance.*' - type: 'gauge' - unit: 'vcpu' - volume: payload.vcpus - user_id: payload.user_id - project_id: payload.tenant_id - resource_id: payload.instance_id - - - name: 'disk.root.size' - event_type: 'compute.instance.*' - type: 'gauge' - unit: 'GB' - volume: payload.root_gb - user_id: payload.user_id - project_id: payload.tenant_id - resource_id: payload.instance_id - - - name: 'disk.ephemeral.size' - event_type: 'compute.instance.*' - type: 'gauge' - unit: 'GB' - volume: payload.ephemeral_gb - user_id: payload.user_id - project_id: payload.tenant_id - resource_id: payload.instance_id - - - name: 'volume.size' - event_type: - - 'volume.exists' - - 'volume.create.*' - - 'volume.delete.*' - - 'volume.resize.*' - - 'volume.attach.*' - - 'volume.detach.*' - - 'volume.update.*' - type: 'gauge' - unit: 'GB' - volume: payload.size - user_id: payload.user_id - project_id: payload.tenant_id - resource_id: payload.volume_id - - - name: 'snapshot.size' - event_type: - - 'snapshot.exists' - - 'snapshot.create.*' - - 'snapshot.delete.*' - type: 'gauge' - unit: 'GB' - volume: payload.volume_size - user_id: payload.user_id - project_id: payload.tenant_id - resource_id: payload.snapshot_id - -# NOTE: non-metric meters are generally events/existence meters -# These are expected to be DEPRECATED in future releases -# - - - name: 'stack.create' - event_type: - - 'orchestration.stack.create.end' - type: 'delta' - unit: 'stack' - volume: 1 - user_id: _context_trustor_user_id - project_id: payload.tenant_id - resource_id: payload.stack_identity - - - name: 'stack.update' - event_type: - - 'orchestration.stack.update.end' - type: 'delta' - unit: 'stack' - volume: 1 - user_id: _context_trustor_user_id - project_id: payload.tenant_id - resource_id: payload.stack_identity - - - name: 'stack.delete' - event_type: - - 'orchestration.stack.delete.end' - type: 'delta' - unit: 'stack' - volume: 1 - user_id: _context_trustor_user_id - project_id: payload.tenant_id - resource_id: payload.stack_identity - - - name: 'stack.resume' - event_type: - - 'orchestration.stack.resume.end' - type: 'delta' - unit: 'stack' - volume: 1 - user_id: _context_trustor_user_id - project_id: payload.tenant_id - resource_id: payload.stack_identity - - - name: 'stack.suspend' - event_type: - - 'orchestration.stack.suspend.end' - type: 'delta' - unit: 'stack' - volume: 1 - user_id: _context_trustor_user_id - project_id: payload.tenant_id - resource_id: payload.stack_identity - - - name: 'magnetodb.table.create' - type: 'gauge' - unit: 'table' - volume: 1 - event_type: 'magnetodb.table.create.end' - resource_id: payload.table_uuid - user_id: _context_user - project_id: _context_tenant - - - name: 'magnetodb.table.delete' - type: 'gauge' - unit: 'table' - volume: 1 - event_type: 'magnetodb.table.delete.end' - resource_id: payload.table_uuid - user_id: _context_user - project_id: _context_tenant - - - name: 'volume' - type: 'gauge' - unit: 'volume' - volume: 1 - event_type: - - 'volume.exists' - - 'volume.create.*' - - 'volume.delete.*' - - 'volume.resize.*' - - 'volume.attach.*' - - 'volume.detach.*' - - 'volume.update.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.exists' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.exists' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.create.start' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.create.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.create.end' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.create.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.delete.start' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.delete.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.delete.end' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.delete.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.update.end' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.update.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.update.start' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.update.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.resize.end' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.resize.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.resize.start' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.resize.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - - name: 'volume.attach.end' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.attach.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.attach.start' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.attach.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.detach.end' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.detach.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'volume.detach.start' - type: 'delta' - unit: 'volume' - volume: 1 - event_type: - - 'volume.detach.*' - resource_id: payload.volume_id - user_id: payload.user_id - project_id: payload.tenant_id - - - - name: 'snapshot' - type: 'gauge' - unit: 'snapshot' - volume: 1 - event_type: - - 'snapshot.exists' - - 'snapshot.create.*' - - 'snapshot.delete.*' - - resource_id: payload.snapshot_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'snapshot.exists' - type: 'delta' - unit: 'snapshot' - volume: 1 - event_type: - - 'snapshot.exists' - resource_id: payload.snapshot_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'snapshot.create.start' - type: 'delta' - unit: 'snapshot' - volume: 1 - event_type: - - 'snapshot.create.*' - resource_id: payload.snapshot_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'snapshot.create.end' - type: 'delta' - unit: 'snapshot' - volume: 1 - event_type: - - 'snapshot.create.*' - resource_id: payload.snapshot_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'snapshot.delete.start' - type: 'delta' - unit: 'snapshot' - volume: 1 - event_type: - - 'snapshot.delete.*' - resource_id: payload.snapshot_id - user_id: payload.user_id - project_id: payload.tenant_id - - - name: 'snapshot.delete.end' - type: 'delta' - unit: 'snapshot' - volume: 1 - event_type: - - 'snapshot.delete.*' - resource_id: payload.snapshot_id - user_id: payload.user_id - project_id: payload.tenant_id \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 6fd51213a1..7b4d2cb52a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,8 +28,6 @@ packages = [entry_points] ceilometer.notification = - magnetodb_table = ceilometer.key_value_storage.notifications:Table - magnetodb_index_count = ceilometer.key_value_storage.notifications:Index instance = ceilometer.compute.notifications.instance:Instance instance_flavor = ceilometer.compute.notifications.instance:InstanceFlavor instance_delete = ceilometer.compute.notifications.instance:InstanceDelete @@ -61,11 +59,6 @@ ceilometer.notification = project = ceilometer.identity.notifications:Project trust = ceilometer.identity.notifications:Trust role_assignment = ceilometer.identity.notifications:RoleAssignment - image_crud = ceilometer.image.notifications:ImageCRUD - image = ceilometer.image.notifications:Image - image_size = ceilometer.image.notifications:ImageSize - image_download = ceilometer.image.notifications:ImageDownload - image_serve = ceilometer.image.notifications:ImageServe network = ceilometer.network.notifications:Network subnet = ceilometer.network.notifications:Subnet port = ceilometer.network.notifications:Port @@ -74,7 +67,6 @@ ceilometer.notification = bandwidth = ceilometer.network.notifications:Bandwidth http.request = ceilometer.middleware:HTTPRequest http.response = ceilometer.middleware:HTTPResponse - stack_crud = ceilometer.orchestration.notifications:StackCRUD data_processing = ceilometer.data_processing.notifications:DataProcessing profiler = ceilometer.profiler.notifications:ProfilerNotifications hardware.ipmi.temperature = ceilometer.ipmi.notifications.ironic:TemperatureSensorNotification @@ -97,6 +89,7 @@ ceilometer.notification = _sample = ceilometer.telemetry.notifications:TelemetryApiPost trove.instance.exists = ceilometer.database.notifications:InstanceExists dns.domain.exists = ceilometer.dns.notifications:DomainExists + meter = ceilometer.meter.notifications:ProcessMeterNotifications ceilometer.discover = local_instances = ceilometer.compute.discovery:InstanceDiscovery