From d2af9a72d5bd7c50192069122f70257789a899ed Mon Sep 17 00:00:00 2001 From: gordon chung Date: Fri, 30 Jan 2015 14:22:32 -0500 Subject: [PATCH] add listener to pick up notification from ceilometermiddleware this patch add listener to create sample/events from new ceilometermiddleware event. Change-Id: Ie770e58b3b9643d07f14cec350235356a0b07b34 Implements: blueprint ceilometermiddleware --- ceilometer/objectstore/notifications.py | 72 ++++++++++++ .../tests/objectstore/test_notifications.py | 106 ++++++++++++++++++ etc/ceilometer/event_definitions.yaml | 36 ++++++ 3 files changed, 214 insertions(+) create mode 100644 ceilometer/objectstore/notifications.py create mode 100644 ceilometer/tests/objectstore/test_notifications.py diff --git a/ceilometer/objectstore/notifications.py b/ceilometer/objectstore/notifications.py new file mode 100644 index 000000000..3b5c19ef6 --- /dev/null +++ b/ceilometer/objectstore/notifications.py @@ -0,0 +1,72 @@ +# +# Copyright 2015 Red Hat. All Rights Reserved. +# +# 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 oslo.messaging +from oslo_config import cfg + +from ceilometer.agent import plugin_base +from ceilometer import sample + +OPTS = [ + cfg.StrOpt('swift_control_exchange', + default='swift', + help="Exchange name for Swift notifications."), +] + + +cfg.CONF.register_opts(OPTS) + + +class _Base(plugin_base.NotificationBase): + """Convert objectstore 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.swift_control_exchange) + for topic in conf.notification_topics] + + +class SwiftWsgiMiddleware(_Base): + + def event_types(self): + return ['objectstore.http.request'] + + def process_notification(self, message): + if message['payload']['measurements']: + for meter in message['payload']['measurements']: + yield sample.Sample.from_notification( + name=meter['metric']['name'], + type=sample.TYPE_DELTA, + unit=meter['metric']['unit'], + volume=meter['result'], + resource_id=message['payload']['target']['id'], + user_id=message['payload']['initiator']['id'], + project_id=message['payload']['initiator']['project_id'], + message=message) + yield sample.Sample.from_notification( + name='storage.api.request', + type=sample.TYPE_DELTA, + unit='request', + volume=1, + resource_id=message['payload']['target']['id'], + user_id=message['payload']['initiator']['id'], + project_id=message['payload']['initiator']['project_id'], + message=message) diff --git a/ceilometer/tests/objectstore/test_notifications.py b/ceilometer/tests/objectstore/test_notifications.py new file mode 100644 index 000000000..e7e4dc0af --- /dev/null +++ b/ceilometer/tests/objectstore/test_notifications.py @@ -0,0 +1,106 @@ +# +# 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. +"""Tests for swift notification events.""" +import mock + +from ceilometer.objectstore import notifications +from ceilometer.tests import base as test + + +MIDDLEWARE_EVENT = { + u'_context_request_id': u'req-a8bfa89b-d28b-4b95-9e4b-7d7875275650', + u'_context_quota_class': None, + u'event_type': u'objectstore.http.request', + u'_context_service_catalog': [], + u'_context_auth_token': None, + u'_context_user_id': None, + u'priority': u'INFO', + u'_context_is_admin': True, + u'_context_user': None, + u'publisher_id': u'ceilometermiddleware', + u'message_id': u'6eccedba-120e-4db8-9735-2ad5f061e5ee', + u'_context_remote_address': None, + u'_context_roles': [], + u'timestamp': u'2013-07-29 06:51:34.474815', + u'_context_timestamp': u'2013-07-29T06:51:34.348091', + u'_unique_id': u'0ee26117077648e18d88ac76e28a72e2', + u'_context_project_name': None, + u'_context_read_deleted': u'no', + u'_context_tenant': None, + u'_context_instance_lock_checked': False, + u'_context_project_id': None, + u'_context_user_name': None, + u'payload': { + 'typeURI': 'http: //schemas.dmtf.org/cloud/audit/1.0/event', + 'eventTime': '2015-01-30T16: 38: 43.233621', + 'target': { + 'action': 'get', + 'typeURI': 'service/storage/object', + 'id': 'account', + 'metadata': { + 'path': '/1.0/CUSTOM_account/container/obj', + 'version': '1.0', + 'container': 'container', + 'object': 'obj' + } + }, + 'observer': { + 'id': 'target' + }, + 'eventType': 'activity', + 'measurements': [ + { + 'metric': { + 'metricId': 'openstack: uuid', + 'name': 'storage.objects.outgoing.bytes', + 'unit': 'B' + }, + 'result': 28 + }, + { + 'metric': { + 'metricId': 'openstack: uuid2', + 'name': 'storage.objects.incoming.bytes', + 'unit': 'B' + }, + 'result': 1 + } + ], + 'initiator': { + 'typeURI': 'service/security/account/user', + 'project_id': None, + 'id': 'openstack: 288f6260-bf37-4737-a178-5038c84ba244' + }, + 'action': 'read', + 'outcome': 'success', + 'id': 'openstack: 69972bb6-14dd-46e4-bdaf-3148014363dc' + } +} + + +class TestMiddlewareNotifications(test.BaseTestCase): + def test_middleware_event(self): + v = notifications.SwiftWsgiMiddleware(mock.Mock()) + samples = list(v.process_notification(MIDDLEWARE_EVENT)) + self.assertEqual(3, len(samples)) + for i in range(2): + measure = MIDDLEWARE_EVENT['payload']['measurements'][i] + self.assertEqual(measure['metric']['name'], samples[i].name) + self.assertEqual(measure['metric']['unit'], samples[i].unit) + self.assertEqual(measure['result'], samples[i].volume) + target = MIDDLEWARE_EVENT['payload']['target'] + initiator = MIDDLEWARE_EVENT['payload']['initiator'] + for i in range(3): + self.assertEqual(target['id'], samples[i].resource_id) + self.assertEqual(initiator['id'], samples[i].user_id) + self.assertEqual(initiator['project_id'], samples[i].project_id) diff --git a/etc/ceilometer/event_definitions.yaml b/etc/ceilometer/event_definitions.yaml index 67bab4911..edd92eb26 100644 --- a/etc/ceilometer/event_definitions.yaml +++ b/etc/ceilometer/event_definitions.yaml @@ -192,3 +192,39 @@ fields: payload.observer.typeURI observer_id: fields: payload.observer.id +- event_type: objectstore.http.request + traits: &objectstore_request + typeURI: + fields: payload.typeURI + id: + fields: payload.id + action: + fields: payload.action + eventType: + fields: payload.eventType + eventTime: + fields: payload.eventTime + outcome: + fields: payload.outcome + initiator_typeURI: + fields: payload.initiator.typeURI + initiator_id: + fields: payload.initiator.id + initiator_project_id: + fields: payload.initiator.project_id + target_typeURI: + fields: payload.target.typeURI + target_id: + fields: payload.target.id + target_action: + fields: payload.target.action + target_metadata_path: + fields: payload.target.metadata.path + target_metadata_version: + fields: payload.target.metadata.version + target_metadata_container: + fields: payload.target.metadata.container + target_metadata_object: + fields: payload.target.metadata.object + observer_id: + fields: payload.observer.id