From 4f4dcfe2dac2e1625a7a5eeda89a76cb93f16f87 Mon Sep 17 00:00:00 2001 From: Ajaya Agrawal Date: Tue, 9 Dec 2014 17:42:10 +0530 Subject: [PATCH] Added metering for magnetodb Wrote notification handler for notifications emitted by Magnetodb and corresponding unittests. Change-Id: I65180aeb43aa2e8a437f7c68391fd03d99669e71 bp: support-magnetodb DocImpact --- ceilometer/key_value_storage/__init__.py | 0 ceilometer/key_value_storage/notifications.py | 79 ++++++++++++ .../tests/key_value_storage/__init__.py | 0 .../key_value_storage/test_notifications.py | 115 ++++++++++++++++++ doc/source/install/manual.rst | 13 ++ doc/source/measurements.rst | 13 ++ setup.cfg | 2 + 7 files changed, 222 insertions(+) create mode 100644 ceilometer/key_value_storage/__init__.py create mode 100644 ceilometer/key_value_storage/notifications.py create mode 100644 ceilometer/tests/key_value_storage/__init__.py create mode 100644 ceilometer/tests/key_value_storage/test_notifications.py diff --git a/ceilometer/key_value_storage/__init__.py b/ceilometer/key_value_storage/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ceilometer/key_value_storage/notifications.py b/ceilometer/key_value_storage/notifications.py new file mode 100644 index 00000000..4eb05e85 --- /dev/null +++ b/ceilometer/key_value_storage/notifications.py @@ -0,0 +1,79 @@ +# 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): + + 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/tests/key_value_storage/__init__.py b/ceilometer/tests/key_value_storage/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ceilometer/tests/key_value_storage/test_notifications.py b/ceilometer/tests/key_value_storage/test_notifications.py new file mode 100644 index 00000000..e385605e --- /dev/null +++ b/ceilometer/tests/key_value_storage/test_notifications.py @@ -0,0 +1,115 @@ +# 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.key_value_storage 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()) + + +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(base.BaseTestCase): + + 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): + handler = notifications.Table(mock.Mock()) + counters = list(handler.process_notification( + NOTIFICATION_TABLE_CREATE)) + self.assertEqual(1, len(counters)) + table = counters[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): + handler = notifications.Table(mock.Mock()) + counters = list(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): + handler = notifications.Index(mock.Mock()) + counters = list(handler.process_notification( + NOTIFICATION_TABLE_CREATE)) + self.assertEqual(1, len(counters)) + table = counters[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/doc/source/install/manual.rst b/doc/source/install/manual.rst index b4fbc15e..810ff27d 100755 --- a/doc/source/install/manual.rst +++ b/doc/source/install/manual.rst @@ -605,6 +605,19 @@ details about any other options you might want to modify before starting the service. +Configuring MagnetoDB to send notifications +=========================================== + +Configure the driver in ``magnetodb-async-task-executor.conf`` + + :: + + notification_driver=messaging + +You also would need to restart the service magnetodb-async-task-executor +(if it's already running) after changing the above configuration file. + + Notifications queues ======================== diff --git a/doc/source/measurements.rst b/doc/source/measurements.rst index 4d561b79..b228de64 100644 --- a/doc/source/measurements.rst +++ b/doc/source/measurements.rst @@ -305,6 +305,19 @@ cluster.delete Delta cluster cluster ID notificati To enable Sahara notifications configure Sahara as described in :ref:`installing_manually`. +Key Value Storage (MagnetoDB) +============================= + +=============================== ========== ========== =========== ============ ================================================= +Name Type Unit Resource Origin Note +=============================== ========== ========== =========== ============ ================================================= +magnetodb.table.create Gauge table table ID notification Creation requests for a table successful +magnetodb.table.delete Gauge table table ID notification Deletion requests for a table successful +magnetodb.table.index.count Gauge index table ID notification Number of indices created in a table +=============================== ========== ========== =========== ============ ================================================= + +To enable MagnetoDB notifications configure MagnetoDB as described in :ref:`installing_manually`. + Energy (Kwapi) ============== diff --git a/setup.cfg b/setup.cfg index 2bba50cf..9823d994 100755 --- a/setup.cfg +++ b/setup.cfg @@ -28,6 +28,8 @@ 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