Listen for volume notifications
This implements bug #1021772 Change-Id: Ic0292e8bdc20668abd331f4f03b06b9d1496217a Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
50da744ed5
commit
b0eb0b091e
@ -43,6 +43,7 @@ LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
COMPUTE_COLLECTOR_NAMESPACE = 'ceilometer.collector.compute'
|
||||
VOLUME_COLLECTOR_NAMESPACE = 'ceilometer.collector.volume'
|
||||
|
||||
|
||||
class CollectorManager(manager.Manager):
|
||||
@ -61,6 +62,10 @@ class CollectorManager(manager.Manager):
|
||||
COMPUTE_COLLECTOR_NAMESPACE,
|
||||
self._publish_counter,
|
||||
)
|
||||
self.volume_handler = dispatcher.NotificationDispatcher(
|
||||
VOLUME_COLLECTOR_NAMESPACE,
|
||||
self._publish_counter,
|
||||
)
|
||||
# FIXME(dhellmann): Should be using create_worker(), except
|
||||
# that notification messages do not conform to the RPC
|
||||
# invocation protocol (they do not include a "method"
|
||||
@ -68,6 +73,9 @@ class CollectorManager(manager.Manager):
|
||||
self.connection.declare_topic_consumer(
|
||||
topic='%s.info' % cfg.CONF.notification_topics[0],
|
||||
callback=self.compute_handler.notify)
|
||||
self.connection.declare_topic_consumer(
|
||||
topic='%s.info' % cfg.CONF.notification_topics[0],
|
||||
callback=self.volume_handler.notify)
|
||||
|
||||
# Set ourselves up as a separate worker for the metering data,
|
||||
# since the default for manager is to use create_consumer().
|
||||
|
@ -35,6 +35,14 @@ class NotificationBase(object):
|
||||
def process_notification(self, message):
|
||||
"""Return a sequence of Counter instances for the given message."""
|
||||
|
||||
def notification_to_metadata(self, event):
|
||||
"""Transform a payload dict to a metadata dict."""
|
||||
metadata = dict([(k, event['payload'].get(k))
|
||||
for k in self.metadata_keys])
|
||||
metadata['event_type'] = event['event_type']
|
||||
metadata['host'] = event['publisher_id']
|
||||
return metadata
|
||||
|
||||
|
||||
class PollsterBase(object):
|
||||
"""Base class for plugins that support the polling API."""
|
||||
|
0
ceilometer/volume/__init__.py
Normal file
0
ceilometer/volume/__init__.py
Normal file
80
ceilometer/volume/notifications.py
Normal file
80
ceilometer/volume/notifications.py
Normal file
@ -0,0 +1,80 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2012 New Dream Network, LLC (DreamHost)
|
||||
#
|
||||
# Author: Julien Danjou <julien@danjou.info>
|
||||
#
|
||||
# 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.
|
||||
"""Converters for producing volume counter messages from cinder notification
|
||||
events.
|
||||
"""
|
||||
|
||||
from ceilometer import counter
|
||||
from ceilometer import plugin
|
||||
|
||||
|
||||
class _Base(plugin.NotificationBase):
|
||||
"""Convert compute.instance.* notifications into Counters
|
||||
"""
|
||||
|
||||
metadata_keys = [
|
||||
"status",
|
||||
"display_name",
|
||||
"volume_type",
|
||||
"size",
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_event_types():
|
||||
return ['volume.exists',
|
||||
'volume.create.end',
|
||||
'volume.delete.end',
|
||||
]
|
||||
|
||||
|
||||
class Volume(_Base):
|
||||
|
||||
def process_notification(self, message):
|
||||
return [
|
||||
counter.Counter(source='?',
|
||||
name='volume',
|
||||
type='absolute',
|
||||
volume=1,
|
||||
user_id=message['payload']['user_id'],
|
||||
project_id=message['payload']['tenant_id'],
|
||||
resource_id=message['payload']['volume_id'],
|
||||
timestamp=message['timestamp'],
|
||||
duration=None,
|
||||
resource_metadata=self.notification_to_metadata(
|
||||
message),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class VolumeSize(_Base):
|
||||
|
||||
def process_notification(self, message):
|
||||
return [
|
||||
counter.Counter(source='?',
|
||||
name='volume_size',
|
||||
type='absolute',
|
||||
volume=message['payload']['size'],
|
||||
user_id=message['payload']['user_id'],
|
||||
project_id=message['payload']['tenant_id'],
|
||||
resource_id=message['payload']['volume_id'],
|
||||
timestamp=message['timestamp'],
|
||||
duration=None,
|
||||
resource_metadata=self.notification_to_metadata(
|
||||
message),
|
||||
),
|
||||
]
|
4
setup.py
4
setup.py
@ -46,6 +46,10 @@ setuptools.setup(
|
||||
root_disk_size = ceilometer.compute.notifications:RootDiskSize
|
||||
ephemeral_disk_size = ceilometer.compute.notifications:EphemeralDiskSize
|
||||
|
||||
[ceilometer.collector.volume]
|
||||
volume = ceilometer.volume.notifications:Volume
|
||||
volume_size = ceilometer.volume.notifications:VolumeSize
|
||||
|
||||
[ceilometer.poll.compute]
|
||||
libvirt_diskio = ceilometer.compute.libvirt:DiskIOPollster
|
||||
libvirt_cpu = ceilometer.compute.libvirt:CPUPollster
|
||||
|
0
tests/volume/__init__.py
Normal file
0
tests/volume/__init__.py
Normal file
91
tests/volume/test_notifications.py
Normal file
91
tests/volume/test_notifications.py
Normal file
@ -0,0 +1,91 @@
|
||||
import unittest
|
||||
|
||||
from ceilometer.volume import notifications
|
||||
|
||||
NOTIFICATION_VOLUME_EXISTS = {
|
||||
u'_context_roles': [u'admin'],
|
||||
u'_context_request_id': u'req-7ef29a5d-adeb-48a8-b104-59c05361aa27',
|
||||
u'_context_quota_class': None,
|
||||
u'event_type': u'volume.exists',
|
||||
u'timestamp': u'2012-09-21 09:29:10.620731',
|
||||
u'message_id': u'e0e6a5ad-2fc9-453c-b3fb-03fe504538dc',
|
||||
u'_context_auth_token': None,
|
||||
u'_context_is_admin': True,
|
||||
u'_context_project_id': None,
|
||||
u'_context_timestamp': u'2012-09-21T09:29:10.266928',
|
||||
u'_context_read_deleted': u'no',
|
||||
u'_context_user_id': None,
|
||||
u'_context_remote_address': None,
|
||||
u'publisher_id': u'volume.ubuntu-VirtualBox',
|
||||
u'payload': {u'status': u'available',
|
||||
u'audit_period_beginning': u'2012-09-20 00:00:00',
|
||||
u'display_name': u'volume1',
|
||||
u'tenant_id': u'6c97f1ecf17047eab696786d56a0bff5',
|
||||
u'created_at': u'2012-09-20 15:05:16',
|
||||
u'snapshot_id': None,
|
||||
u'volume_type': None,
|
||||
u'volume_id': u'84c363b9-9854-48dc-b949-fe04263f4cf0',
|
||||
u'audit_period_ending': u'2012-09-21 00:00:00',
|
||||
u'user_id': u'4d2fa4b76a4a4ecab8c468c8dea42f89',
|
||||
u'launched_at': u'2012-09-20 15:05:23',
|
||||
u'size': 1},
|
||||
u'priority': u'INFO'
|
||||
}
|
||||
|
||||
|
||||
NOTIFICATION_VOLUME_DELETE = {
|
||||
u'_context_roles': [u'Member', u'admin'],
|
||||
u'_context_request_id': u'req-6ba8ccb4-1093-4a39-b029-adfaa3fc7ceb',
|
||||
u'_context_quota_class': None,
|
||||
u'event_type': u'volume.delete.end',
|
||||
u'timestamp': u'2012-09-21 10:24:13.168630',
|
||||
u'message_id': u'f6e6bc1f-fcd5-41e1-9a86-da7d024f03d9',
|
||||
u'_context_auth_token': u'277c6899de8a4b3d999f3e2e4c0915ff',
|
||||
u'_context_is_admin': True,
|
||||
u'_context_project_id': u'6c97f1ecf17047eab696786d56a0bff5',
|
||||
u'_context_timestamp': u'2012-09-21T10:23:54.741228',
|
||||
u'_context_read_deleted': u'no',
|
||||
u'_context_user_id': u'4d2fa4b76a4a4ecab8c468c8dea42f89',
|
||||
u'_context_remote_address': u'192.168.22.101',
|
||||
u'publisher_id': u'volume.ubuntu-VirtualBox',
|
||||
u'payload': {u'status': u'deleting',
|
||||
u'volume_type_id': None,
|
||||
u'display_name': u'abc',
|
||||
u'tenant_id': u'6c97f1ecf17047eab696786d56a0bff5',
|
||||
u'created_at': u'2012-09-21 10:10:47',
|
||||
u'snapshot_id': None,
|
||||
u'volume_id': u'3b761164-84b4-4eb3-8fcb-1974c641d6ef',
|
||||
u'user_id': u'4d2fa4b76a4a4ecab8c468c8dea42f89',
|
||||
u'launched_at': u'2012-09-21 10:10:50',
|
||||
u'size': 1},
|
||||
u'priority': u'INFO'}
|
||||
|
||||
|
||||
class TestNotifications(unittest.TestCase):
|
||||
def test_volume_exists(self):
|
||||
v = notifications.Volume()
|
||||
counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS)
|
||||
self.assertEqual(len(counters), 1)
|
||||
c = counters[0]
|
||||
self.assertEqual(c.volume, 1)
|
||||
|
||||
def test_volume_size_exists(self):
|
||||
v = notifications.VolumeSize()
|
||||
counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS)
|
||||
self.assertEqual(len(counters), 1)
|
||||
c = counters[0]
|
||||
self.assertEqual(c.volume, NOTIFICATION_VOLUME_EXISTS['payload']['size'])
|
||||
|
||||
def test_volume_delete(self):
|
||||
v = notifications.Volume()
|
||||
counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS)
|
||||
self.assertEqual(len(counters), 1)
|
||||
c = counters[0]
|
||||
self.assertEqual(c.volume, 1)
|
||||
|
||||
def test_volume_size_delete(self):
|
||||
v = notifications.VolumeSize()
|
||||
counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS)
|
||||
self.assertEqual(len(counters), 1)
|
||||
c = counters[0]
|
||||
self.assertEqual(c.volume, NOTIFICATION_VOLUME_EXISTS['payload']['size'])
|
Loading…
Reference in New Issue
Block a user