diff --git a/ceilometer/compute/instance.py b/ceilometer/compute/instance.py deleted file mode 100644 index 4914c1b80..000000000 --- a/ceilometer/compute/instance.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Copyright © 2012 New Dream Network, LLC (DreamHost) -# -# Author: Doug Hellmann -# -# 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. -"""Common code for working with instances -""" -from oslo.config import cfg - -OPTS = [ - cfg.ListOpt('reserved_metadata_namespace', - default=['metering.'], - help='list of metadata prefixes resevred for metering use', - ), - cfg.IntOpt('reserved_metadata_length', - default=256, - help='limit on length of reserved metadata values'), -] - -cfg.CONF.register_opts(OPTS) - -INSTANCE_PROPERTIES = [ - # Identity properties - 'reservation_id', - # Type properties - 'architecture', - # Location properties - 'kernel_id', - 'os_type', - 'ramdisk_id', - # Capacity properties - 'ephemeral_gb', - 'root_gb'] - - -def add_reserved_user_metadata(instance, metadata): - limit = cfg.CONF.reserved_metadata_length - user_metadata = {} - for prefix in cfg.CONF.reserved_metadata_namespace: - md = dict( - (k[len(prefix):].replace('.', '_'), - v[:limit] if isinstance(v, basestring) else v) - for k, v in instance.metadata.items() - if (k.startswith(prefix) and - k[len(prefix):].replace('.', '_') not in metadata) - ) - user_metadata.update(md) - if user_metadata: - metadata['user_metadata'] = user_metadata - - return metadata - - -def get_metadata_from_object(instance): - """Return a metadata dictionary for the instance. - """ - metadata = { - 'availability_zone': getattr(instance, - 'OS-EXT-AZ:availability_zone', u''), - 'display_name': instance.name, - 'name': getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', u''), - 'instance_type': (instance.flavor['id'] if instance.flavor else None), - 'disk_gb': (instance.flavor['disk'] if instance.flavor else None), - 'memory_mb': (instance.flavor['ram'] if instance.flavor else None), - 'vcpus': (instance.flavor['vcpus'] if instance.flavor else None), - 'host': instance.hostId, - # Image properties - 'image_ref': (instance.image['id'] if instance.image else None), - } - - # Images that come through the conductor API in the nova notifier - # plugin will not have links. - if instance.image and instance.image.get('links'): - metadata['image_ref_url'] = instance.image['links'][0]['href'] - else: - metadata['image_ref_url'] = None - - for name in INSTANCE_PROPERTIES: - metadata[name] = getattr(instance, name, u'') - - return add_reserved_user_metadata(instance, metadata) diff --git a/ceilometer/compute/notifications.py b/ceilometer/compute/notifications.py index f46d11c57..cac9f59bc 100644 --- a/ceilometer/compute/notifications.py +++ b/ceilometer/compute/notifications.py @@ -22,10 +22,8 @@ from oslo.config import cfg -from ceilometer.compute import instance from ceilometer import counter from ceilometer import plugin -from ceilometer import utils OPTS = [ @@ -39,7 +37,6 @@ cfg.CONF.register_opts(OPTS) class ComputeNotificationBase(plugin.NotificationBase): - @staticmethod def get_exchange_topics(conf): """Return a sequence of ExchangeTopics defining the exchange and @@ -54,50 +51,27 @@ class ComputeNotificationBase(plugin.NotificationBase): class InstanceScheduled(ComputeNotificationBase): - - metadata_keys = ['request_spec'] - @staticmethod def get_event_types(): return ['scheduler.run_instance.scheduled'] - def notification_to_metadata(self, event): - metadata = super(InstanceScheduled, - self).notification_to_metadata(event) - metadata['weighted_host'] = event['payload']['weighted_host']['host'] - metadata['weight'] = event['payload']['weighted_host']['weight'] - return metadata - def process_notification(self, message): - return [ - counter.Counter( - name='instance.scheduled', - type=counter.TYPE_DELTA, - volume=1, - unit='instance', - user_id=None, - project_id= - message['payload']['request_spec'] - ['instance_properties']['project_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=dict( - utils.recursive_keypairs(message['payload'])), - ) - ] + yield counter.Counter.from_notification( + name='instance.scheduled', + type=counter.TYPE_DELTA, + volume=1, + unit='instance', + user_id=None, + project_id= + message['payload']['request_spec'] + ['instance_properties']['project_id'], + resource_id=message['payload']['instance_id'], + message=message) class ComputeInstanceNotificationBase(ComputeNotificationBase): """Convert compute.instance.* notifications into Counters """ - metadata_keys = instance.INSTANCE_PROPERTIES - - def notification_to_metadata(self, event): - metadata = super(ComputeInstanceNotificationBase, - self).notification_to_metadata(event) - metadata['instance_type'] = event['payload']['instance_type_id'] - return metadata - @staticmethod def get_event_types(): return ['compute.instance.create.end', @@ -108,112 +82,83 @@ class ComputeInstanceNotificationBase(ComputeNotificationBase): class Instance(ComputeInstanceNotificationBase): - def process_notification(self, message): - return [ - counter.Counter(name='instance', - type=counter.TYPE_GAUGE, - unit='instance', - volume=1, - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message), - ), - ] + yield counter.Counter.from_notification( + name='instance', + type=counter.TYPE_GAUGE, + unit='instance', + volume=1, + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) class Memory(ComputeInstanceNotificationBase): - def process_notification(self, message): - return [ - counter.Counter(name='memory', - type=counter.TYPE_GAUGE, - unit='MB', - volume=message['payload']['memory_mb'], - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message)), - ] + yield counter.Counter.from_notification( + name='memory', + type=counter.TYPE_GAUGE, + unit='MB', + volume=message['payload']['memory_mb'], + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) class VCpus(ComputeInstanceNotificationBase): - def process_notification(self, message): - return [ - counter.Counter(name='vcpus', - type=counter.TYPE_GAUGE, - unit='vcpu', - volume=message['payload']['vcpus'], - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message)), - ] + yield counter.Counter.from_notification( + name='vcpus', + type=counter.TYPE_GAUGE, + unit='vcpu', + volume=message['payload']['vcpus'], + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) class RootDiskSize(ComputeInstanceNotificationBase): - def process_notification(self, message): - return [ - counter.Counter(name='disk.root.size', - type=counter.TYPE_GAUGE, - unit='GB', - volume=message['payload']['root_gb'], - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message)), - ] + yield counter.Counter.from_notification( + name='disk.root.size', + type=counter.TYPE_GAUGE, + unit='GB', + volume=message['payload']['root_gb'], + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) class EphemeralDiskSize(ComputeInstanceNotificationBase): - def process_notification(self, message): - return [ - counter.Counter(name='disk.ephemeral.size', - type=counter.TYPE_GAUGE, - unit='GB', - volume=message['payload']['ephemeral_gb'], - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message)), - ] + yield counter.Counter.from_notification( + name='disk.ephemeral.size', + type=counter.TYPE_GAUGE, + unit='GB', + volume=message['payload']['ephemeral_gb'], + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) class InstanceFlavor(ComputeInstanceNotificationBase): - def process_notification(self, message): - counters = [] instance_type = message.get('payload', {}).get('instance_type') if instance_type: - counters.append( - counter.Counter( - name='instance:%s' % instance_type, - type=counter.TYPE_GAUGE, - unit='instance', - volume=1, - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message), - ) - ) - return counters + yield counter.Counter.from_notification( + name='instance:%s' % instance_type, + type=counter.TYPE_GAUGE, + unit='instance', + volume=1, + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) class InstanceDelete(ComputeInstanceNotificationBase): @@ -226,17 +171,13 @@ class InstanceDelete(ComputeInstanceNotificationBase): return ['compute.instance.delete.samples'] def process_notification(self, message): - return [ - counter.Counter(name=sample['name'], - type=sample['type'], - unit=sample['unit'], - volume=sample['volume'], - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['instance_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message), - ) - for sample in message['payload'].get('samples', []) - ] + for sample in message['payload'].get('samples', []): + yield counter.Counter.from_notification( + name=sample['name'], + type=sample['type'], + unit=sample['unit'], + volume=sample['volume'], + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['instance_id'], + message=message) diff --git a/ceilometer/compute/pollsters.py b/ceilometer/compute/pollsters.py index aa333eabd..d9c05dd6e 100644 --- a/ceilometer/compute/pollsters.py +++ b/ceilometer/compute/pollsters.py @@ -21,7 +21,8 @@ import copy import datetime -from ceilometer.compute import instance as compute_instance +from oslo.config import cfg + from ceilometer.compute import plugin from ceilometer import counter from ceilometer.openstack.common import log @@ -30,6 +31,78 @@ from ceilometer.openstack.common import timeutils LOG = log.getLogger(__name__) +INSTANCE_PROPERTIES = [ + # Identity properties + 'reservation_id', + # Type properties + 'architecture', + 'OS-EXT-AZ:availability_zone', + 'kernel_id', + 'os_type', + 'ramdisk_id', + # Capacity properties + 'disk_gb', + 'ephemeral_gb', + 'memory_mb', + 'root_gb', + 'vcpus'] + +OPTS = [ + cfg.ListOpt('reserved_metadata_namespace', + default=['metering.'], + help='list of metadata prefixes reserved for metering use'), + cfg.IntOpt('reserved_metadata_length', + default=256, + help='limit on length of reserved metadata values'), +] + +cfg.CONF.register_opts(OPTS) + + +def _add_reserved_user_metadata(instance, metadata): + limit = cfg.CONF.reserved_metadata_length + user_metadata = {} + for prefix in cfg.CONF.reserved_metadata_namespace: + md = dict( + (k[len(prefix):].replace('.', '_'), + v[:limit] if isinstance(v, basestring) else v) + for k, v in instance.metadata.items() + if (k.startswith(prefix) and + k[len(prefix):].replace('.', '_') not in metadata) + ) + user_metadata.update(md) + if user_metadata: + metadata['user_metadata'] = user_metadata + + return metadata + + +def _get_metadata_from_object(instance): + """Return a metadata dictionary for the instance. + """ + metadata = { + 'display_name': instance.name, + 'name': getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', u''), + 'instance_type': (instance.flavor['id'] if instance.flavor else None), + 'host': instance.hostId, + 'flavor': instance.flavor, + # Image properties + 'image': instance.image, + 'image_ref': (instance.image['id'] if instance.image else None), + } + + # Images that come through the conductor API in the nova notifier + # plugin will not have links. + if instance.image and instance.image.get('links'): + metadata['image_ref_url'] = instance.image['links'][0]['href'] + else: + metadata['image_ref_url'] = None + + for name in INSTANCE_PROPERTIES: + metadata[name] = getattr(instance, name, u'') + return _add_reserved_user_metadata(instance, metadata) + + def _instance_name(instance): """Shortcut to get instance name.""" return getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', None) @@ -45,7 +118,7 @@ def make_counter_from_instance(instance, name, type, unit, volume): project_id=instance.tenant_id, resource_id=instance.id, timestamp=timeutils.isotime(), - resource_metadata=compute_instance.get_metadata_from_object(instance), + resource_metadata=_get_metadata_from_object(instance), ) diff --git a/ceilometer/counter.py b/ceilometer/counter.py index fda5c39f5..48737760a 100644 --- a/ceilometer/counter.py +++ b/ceilometer/counter.py @@ -23,6 +23,7 @@ in by the plugins that create them. """ import collections +import copy from oslo.config import cfg @@ -67,3 +68,23 @@ Counter = collections.namedtuple('Counter', TYPE_GAUGE = 'gauge' TYPE_DELTA = 'delta' TYPE_CUMULATIVE = 'cumulative' + + +def from_notification(cls, name, type, volume, unit, + user_id, project_id, resource_id, + message): + metadata = copy.copy(message['payload']) + metadata['event_type'] = message['event_type'] + metadata['host'] = message['publisher_id'] + return cls(name=name, + type=type, + volume=volume, + unit=unit, + user_id=user_id, + project_id=project_id, + resource_id=resource_id, + timestamp=message['timestamp'], + resource_metadata=metadata) + + +Counter.from_notification = classmethod(from_notification) diff --git a/ceilometer/image/notifications.py b/ceilometer/image/notifications.py index cfee9aab3..a601bd277 100644 --- a/ceilometer/image/notifications.py +++ b/ceilometer/image/notifications.py @@ -51,25 +51,6 @@ class ImageBase(plugin.NotificationBase): class ImageCRUDBase(ImageBase): - - metadata_keys = [ - 'name', - 'size', - 'status', - 'disk_format', - 'container_format', - 'location', - 'deleted', - 'created_at', - 'updated_at', - 'properties', - 'protected', - 'checksum', - 'is_public', - 'deleted_at', - 'min_ram', - ] - @staticmethod def get_event_types(): return [ @@ -80,67 +61,46 @@ class ImageCRUDBase(ImageBase): class ImageCRUD(ImageCRUDBase): - def process_notification(self, message): - metadata = self.notification_to_metadata(message) - return [ - counter.Counter( - name=message['event_type'], - type=counter.TYPE_DELTA, - unit='image', - volume=1, - resource_id=message['payload']['id'], - user_id=None, - project_id=message['payload']['owner'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ), - ] + yield counter.Counter.from_notification( + name=message['event_type'], + type=counter.TYPE_DELTA, + unit='image', + volume=1, + resource_id=message['payload']['id'], + user_id=None, + project_id=message['payload']['owner'], + message=message) class Image(ImageCRUDBase): - def process_notification(self, message): - metadata = self.notification_to_metadata(message) - return [ - counter.Counter( - name='image', - type=counter.TYPE_GAUGE, - unit='image', - volume=1, - resource_id=message['payload']['id'], - user_id=None, - project_id=message['payload']['owner'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ), - ] + yield counter.Counter.from_notification( + name='image', + type=counter.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): - metadata = self.notification_to_metadata(message) - return [ - counter.Counter( - name='image.size', - type=counter.TYPE_GAUGE, - unit='B', - volume=message['payload']['size'], - resource_id=message['payload']['id'], - user_id=None, - project_id=message['payload']['owner'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ), - ] + yield counter.Counter.from_notification( + name='image.size', + type=counter.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 counter when an image is downloaded.""" - - metadata_keys = ['destination_ip', 'owner_id'] - @staticmethod def get_event_types(): return [ @@ -148,28 +108,19 @@ class ImageDownload(ImageBase): ] def process_notification(self, message): - metadata = self.notification_to_metadata(message) - return [ - counter.Counter( - name='image.download', - type=counter.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'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ), - ] + yield counter.Counter.from_notification( + name='image.download', + type=counter.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 counter when an image is served out.""" - - metadata_keys = ['destination_ip', 'receiver_user_id', - 'receiver_tenant_id'] - @staticmethod def get_event_types(): return [ @@ -177,17 +128,12 @@ class ImageServe(ImageBase): ] def process_notification(self, message): - metadata = self.notification_to_metadata(message) - return [ - counter.Counter( - name='image.serve', - type=counter.TYPE_DELTA, - unit='B', - volume=message['payload']['bytes_sent'], - resource_id=message['payload']['image_id'], - user_id=None, - project_id=message['payload']['owner_id'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ), - ] + yield counter.Counter.from_notification( + name='image.serve', + type=counter.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/network/notifications.py b/ceilometer/network/notifications.py index 71843cb46..26ba0dd52 100644 --- a/ceilometer/network/notifications.py +++ b/ceilometer/network/notifications.py @@ -72,34 +72,31 @@ class NetworkNotificationBase(plugin.NotificationBase): def process_notification(self, message): LOG.info('network notification %r', message) message['payload'] = message['payload'][self.resource_name] - metadata = self.notification_to_metadata(message) counter_name = getattr(self, 'counter_name', self.resource_name) unit_value = getattr(self, 'unit', self.resource_name) - yield counter.Counter(name=counter_name, - type=counter.TYPE_GAUGE, - unit=unit_value, - volume=1, - user_id=message['_context_user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['id'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ) + yield counter.Counter.from_notification( + name=counter_name, + type=counter.TYPE_GAUGE, + unit=unit_value, + volume=1, + user_id=message['_context_user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['id'], + message=message) event_type_split = message['event_type'].split('.') if len(event_type_split) > 2: - yield counter.Counter(name=counter_name - + "." + event_type_split[1], - type=counter.TYPE_DELTA, - unit=unit_value, - volume=1, - user_id=message['_context_user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['id'], - timestamp=message['timestamp'], - resource_metadata=metadata, - ) + yield counter.Counter.from_notification( + name=counter_name + + "." + event_type_split[1], + type=counter.TYPE_DELTA, + unit=unit_value, + volume=1, + user_id=message['_context_user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['id'], + message=message) class Network(NetworkNotificationBase): @@ -107,16 +104,6 @@ class Network(NetworkNotificationBase): metering framework. """ - - metadata_keys = [ - "status", - "subnets", - "name", - "router:external", - "admin_state_up", - "shared", - ] - resource_name = 'network' @@ -125,19 +112,6 @@ class Subnet(NetworkNotificationBase): metering framework. """ - - metadata_keys = [ - "name", - "enable_dhcp", - "network_id", - "dns_nameservers", - "allocation_pools", - "host_routes", - "ip_version", - "gateway_ip", - "cidr", - ] - resource_name = 'subnet' @@ -146,18 +120,6 @@ class Port(NetworkNotificationBase): metering framework. """ - - metadata_keys = [ - "status", - "name", - "admin_state_up", - "network_id", - "device_owner", - "mac_address", - "fixed_ips", - "device_id", - ] - resource_name = 'port' @@ -166,14 +128,6 @@ class Router(NetworkNotificationBase): metering framework. """ - - metadata_keys = [ - "status", - "external_gateway_info", - "admin_state_up", - "name", - ] - resource_name = 'router' @@ -182,15 +136,6 @@ class FloatingIP(NetworkNotificationBase): metering framework. """ - - metadata_keys = [ - "router_id", - "floating_network_id", - "fixed_ip_address", - "floating_ip_address", - "port_id", - ] - resource_name = 'floatingip' counter_name = 'ip.floating' unit = 'ip' diff --git a/ceilometer/plugin.py b/ceilometer/plugin.py index bcd51d1b3..b06f51343 100644 --- a/ceilometer/plugin.py +++ b/ceilometer/plugin.py @@ -69,14 +69,6 @@ class NotificationBase(PluginBase): :param message: Message to process. """ - 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(PluginBase): """Base class for plugins that support the polling API.""" diff --git a/ceilometer/volume/notifications.py b/ceilometer/volume/notifications.py index a756d3580..003c7e583 100644 --- a/ceilometer/volume/notifications.py +++ b/ceilometer/volume/notifications.py @@ -36,15 +36,7 @@ cfg.CONF.register_opts(OPTS) class _Base(plugin.NotificationBase): - """Convert volume notifications into Counters - """ - - metadata_keys = [ - "status", - "display_name", - "volume_type", - "size", - ] + """Convert volume notifications into Counters.""" @staticmethod def get_exchange_topics(conf): @@ -66,36 +58,26 @@ class _Base(plugin.NotificationBase): class Volume(_Base): - def process_notification(self, message): - return [ - counter.Counter(name='volume', - type=counter.TYPE_GAUGE, - unit='volume', - volume=1, - user_id=message['payload']['user_id'], - project_id=message['payload']['tenant_id'], - resource_id=message['payload']['volume_id'], - timestamp=message['timestamp'], - resource_metadata=self.notification_to_metadata( - message), - ), - ] + yield counter.Counter.from_notification( + name='volume', + type=counter.TYPE_GAUGE, + unit='volume', + volume=1, + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['volume_id'], + message=message) class VolumeSize(_Base): - def process_notification(self, message): - return [ - counter.Counter(name='volume.size', - type=counter.TYPE_GAUGE, - unit='GB', - 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'], - resource_metadata=self.notification_to_metadata( - message), - ), - ] + yield counter.Counter.from_notification( + name='volume.size', + type=counter.TYPE_GAUGE, + unit='GB', + volume=message['payload']['size'], + user_id=message['payload']['user_id'], + project_id=message['payload']['tenant_id'], + resource_id=message['payload']['volume_id'], + message=message) diff --git a/etc/ceilometer/ceilometer.conf.sample b/etc/ceilometer/ceilometer.conf.sample index 78b811a7f..2f38aa33e 100644 --- a/etc/ceilometer/ceilometer.conf.sample +++ b/etc/ceilometer/ceilometer.conf.sample @@ -28,18 +28,6 @@ #enable_v1_api=true -# -# Options defined in ceilometer.compute.instance -# - -# list of metadata prefixes resevred for metering use (list -# value) -#reserved_metadata_namespace=metering. - -# limit on length of reserved metadata values (integer value) -#reserved_metadata_length=256 - - # # Options defined in ceilometer.compute.notifications # @@ -48,6 +36,18 @@ #nova_control_exchange=nova +# +# Options defined in ceilometer.compute.pollsters +# + +# list of metadata prefixes reserved for metering use (list +# value) +#reserved_metadata_namespace=metering. + +# limit on length of reserved metadata values (integer value) +#reserved_metadata_length=256 + + # # Options defined in ceilometer.compute.virt.inspector # diff --git a/tests/compute/test_instance.py b/tests/compute/test_instance.py deleted file mode 100644 index 26576c330..000000000 --- a/tests/compute/test_instance.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Copyright © 2012 New Dream Network, LLC (DreamHost) -# -# Author: Doug Hellmann -# -# 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 ceilometer.compute.instance -""" - -import mock - -from ceilometer.compute import instance -from ceilometer.compute import manager -from ceilometer.tests import base - - -class FauxInstance(object): - - def __init__(self, **kwds): - for name, value in kwds.items(): - setattr(self, name, value) - - def __getitem__(self, key): - return getattr(self, key) - - def get(self, key, default): - try: - return getattr(self, key) - except AttributeError: - return default - - -class TestLocationMetadata(base.TestCase): - - @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock()) - def setUp(self): - self.manager = manager.AgentManager() - super(TestLocationMetadata, self).setUp() - - # Mimics an instance returned from nova api call - self.INSTANCE_PROPERTIES = {'name': 'display name', - 'OS-EXT-SRV-ATTR:instance_name': - 'instance-000001', - 'availability_zone': None, - 'OS-EXT-AZ:availability_zone': - 'foo-zone', - 'reservation_id': 'reservation id', - 'architecture': 'x86_64', - 'kernel_id': 'kernel id', - 'os_type': 'linux', - 'ramdisk_id': 'ramdisk id', - 'ephemeral_gb': 7, - 'root_gb': 3, - 'image': {'id': 1, - 'links': [{"rel": "bookmark", - 'href': 2}]}, - 'hostId': '1234-5678', - 'flavor': {'id': 1, - 'disk': 0, - 'ram': 512, - 'vcpus': 2}, - 'metadata': {'metering.autoscale.group': - 'X' * 512, - 'metering.ephemeral_gb': 42}} - - self.instance = FauxInstance(**self.INSTANCE_PROPERTIES) - - def test_metadata(self): - md = instance.get_metadata_from_object(self.instance) - iprops = self.INSTANCE_PROPERTIES - self.assertEqual(md['availability_zone'], - iprops['OS-EXT-AZ:availability_zone']) - self.assertEqual(md['name'], iprops['OS-EXT-SRV-ATTR:instance_name']) - self.assertEqual(md['disk_gb'], iprops['flavor']['disk']) - self.assertEqual(md['display_name'], iprops['name']) - self.assertEqual(md['instance_type'], iprops['flavor']['id']) - self.assertEqual(md['image_ref'], iprops['image']['id']) - self.assertEqual(md['image_ref_url'], - iprops['image']['links'][0]['href']) - self.assertEqual(md['memory_mb'], iprops['flavor']['ram']) - self.assertEqual(md['vcpus'], iprops['flavor']['vcpus']) - self.assertEqual(md['host'], iprops['hostId']) - - self.assertEqual(md['reservation_id'], iprops['reservation_id']) - self.assertEqual(md['kernel_id'], iprops['kernel_id']) - self.assertEqual(md['ramdisk_id'], iprops['ramdisk_id']) - self.assertEqual(md['architecture'], iprops['architecture']) - self.assertEqual(md['os_type'], iprops['os_type']) - self.assertEqual(md['ephemeral_gb'], iprops['ephemeral_gb']) - self.assertEqual(md['root_gb'], iprops['root_gb']) - user_metadata = md['user_metadata'] - expected = iprops['metadata']['metering.autoscale.group'][:256] - self.assertEqual(user_metadata['autoscale_group'], expected) - self.assertEqual(len(user_metadata), 1) - - def test_metadata_empty_image(self): - self.INSTANCE_PROPERTIES['image'] = '' - self.instance = FauxInstance(**self.INSTANCE_PROPERTIES) - md = instance.get_metadata_from_object(self.instance) - self.assertEqual(md['image_ref'], None) - self.assertEqual(md['image_ref_url'], None) diff --git a/tests/compute/test_notifications.py b/tests/compute/test_notifications.py index 4d1202c2d..b2db04903 100644 --- a/tests/compute/test_notifications.py +++ b/tests/compute/test_notifications.py @@ -401,9 +401,9 @@ INSTANCE_SCHEDULED = { class TestNotifications(base.TestCase): def test_process_notification(self): - info = notifications.Instance().process_notification( + info = list(notifications.Instance().process_notification( INSTANCE_CREATE_END - )[0] + ))[0] for name, actual, expected in [ ('counter_name', info.name, 'instance'), ('counter_type', info.type, counter.TYPE_GAUGE), @@ -412,7 +412,8 @@ class TestNotifications(base.TestCase): INSTANCE_CREATE_END['timestamp']), ('resource_id', info.resource_id, INSTANCE_CREATE_END['payload']['instance_id']), - ('instance_type', info.resource_metadata['instance_type'], + ('instance_type_id', + info.resource_metadata['instance_type_id'], INSTANCE_CREATE_END['payload']['instance_type_id']), ('host', info.resource_metadata['host'], INSTANCE_CREATE_END['publisher_id']), @@ -425,42 +426,42 @@ class TestNotifications(base.TestCase): def test_instance_create_instance(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_CREATE_END) + counters = list(ic.process_notification(INSTANCE_CREATE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, 1) def test_instance_create_flavor(self): ic = notifications.InstanceFlavor() - counters = ic.process_notification(INSTANCE_CREATE_END) + counters = list(ic.process_notification(INSTANCE_CREATE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, 1) def test_instance_create_memory(self): ic = notifications.Memory() - counters = ic.process_notification(INSTANCE_CREATE_END) + counters = list(ic.process_notification(INSTANCE_CREATE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['memory_mb']) def test_instance_create_vcpus(self): ic = notifications.VCpus() - counters = ic.process_notification(INSTANCE_CREATE_END) + counters = list(ic.process_notification(INSTANCE_CREATE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['vcpus']) def test_instance_create_root_disk_size(self): ic = notifications.RootDiskSize() - counters = ic.process_notification(INSTANCE_CREATE_END) + counters = list(ic.process_notification(INSTANCE_CREATE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['root_gb']) def test_instance_create_ephemeral_disk_size(self): ic = notifications.EphemeralDiskSize() - counters = ic.process_notification(INSTANCE_CREATE_END) + counters = list(ic.process_notification(INSTANCE_CREATE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, @@ -468,34 +469,34 @@ class TestNotifications(base.TestCase): def test_instance_exists_instance(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_EXISTS) + counters = list(ic.process_notification(INSTANCE_EXISTS)) self.assertEqual(len(counters), 1) def test_instance_exists_flavor(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_EXISTS) + counters = list(ic.process_notification(INSTANCE_EXISTS)) self.assertEqual(len(counters), 1) def test_instance_delete_instance(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_DELETE_START) + counters = list(ic.process_notification(INSTANCE_DELETE_START)) self.assertEqual(len(counters), 1) def test_instance_delete_flavor(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_DELETE_START) + counters = list(ic.process_notification(INSTANCE_DELETE_START)) self.assertEqual(len(counters), 1) def test_instance_finish_resize_instance(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_FINISH_RESIZE_END) + counters = list(ic.process_notification(INSTANCE_FINISH_RESIZE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, 1) def test_instance_finish_resize_flavor(self): ic = notifications.InstanceFlavor() - counters = ic.process_notification(INSTANCE_FINISH_RESIZE_END) + counters = list(ic.process_notification(INSTANCE_FINISH_RESIZE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, 1) @@ -503,7 +504,7 @@ class TestNotifications(base.TestCase): def test_instance_finish_resize_memory(self): ic = notifications.Memory() - counters = ic.process_notification(INSTANCE_FINISH_RESIZE_END) + counters = list(ic.process_notification(INSTANCE_FINISH_RESIZE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, @@ -511,7 +512,7 @@ class TestNotifications(base.TestCase): def test_instance_finish_resize_vcpus(self): ic = notifications.VCpus() - counters = ic.process_notification(INSTANCE_FINISH_RESIZE_END) + counters = list(ic.process_notification(INSTANCE_FINISH_RESIZE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, @@ -519,14 +520,14 @@ class TestNotifications(base.TestCase): def test_instance_resize_finish_instance(self): ic = notifications.Instance() - counters = ic.process_notification(INSTANCE_FINISH_RESIZE_END) + counters = list(ic.process_notification(INSTANCE_FINISH_RESIZE_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, 1) def test_instance_resize_finish_flavor(self): ic = notifications.InstanceFlavor() - counters = ic.process_notification(INSTANCE_RESIZE_REVERT_END) + counters = list(ic.process_notification(INSTANCE_RESIZE_REVERT_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, 1) @@ -534,7 +535,7 @@ class TestNotifications(base.TestCase): def test_instance_resize_finish_memory(self): ic = notifications.Memory() - counters = ic.process_notification(INSTANCE_RESIZE_REVERT_END) + counters = list(ic.process_notification(INSTANCE_RESIZE_REVERT_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, @@ -542,7 +543,7 @@ class TestNotifications(base.TestCase): def test_instance_resize_finish_vcpus(self): ic = notifications.VCpus() - counters = ic.process_notification(INSTANCE_RESIZE_REVERT_END) + counters = list(ic.process_notification(INSTANCE_RESIZE_REVERT_END)) self.assertEqual(len(counters), 1) c = counters[0] self.assertEqual(c.volume, @@ -550,7 +551,7 @@ class TestNotifications(base.TestCase): def test_instance_delete_samples(self): ic = notifications.InstanceDelete() - counters = ic.process_notification(INSTANCE_DELETE_SAMPLES) + counters = list(ic.process_notification(INSTANCE_DELETE_SAMPLES)) self.assertEqual(len(counters), 2) names = [c.name for c in counters] self.assertEqual(names, ['sample-name1', 'sample-name2']) @@ -561,7 +562,7 @@ class TestNotifications(base.TestCase): self.assertIn(INSTANCE_SCHEDULED['event_type'], ic.get_event_types()) - counters = ic.process_notification(INSTANCE_SCHEDULED) + counters = list(ic.process_notification(INSTANCE_SCHEDULED)) self.assertEqual(len(counters), 1) names = [c.name for c in counters] self.assertEqual(names, ['instance.scheduled']) diff --git a/tests/compute/test_pollsters.py b/tests/compute/test_pollsters.py index 4afc1ea1d..dc729ae30 100644 --- a/tests/compute/test_pollsters.py +++ b/tests/compute/test_pollsters.py @@ -29,6 +29,82 @@ from ceilometer.compute.virt import inspector as virt_inspector from ceilometer.tests import base as test_base +class FauxInstance(object): + + def __init__(self, **kwds): + for name, value in kwds.items(): + setattr(self, name, value) + + def __getitem__(self, key): + return getattr(self, key) + + def get(self, key, default): + try: + return getattr(self, key) + except AttributeError: + return default + + +class TestLocationMetadata(test_base.TestCase): + + @mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock()) + def setUp(self): + self.manager = manager.AgentManager() + super(TestLocationMetadata, self).setUp() + + # Mimics an instance returned from nova api call + self.INSTANCE_PROPERTIES = {'name': 'display name', + 'OS-EXT-SRV-ATTR:instance_name': + 'instance-000001', + 'OS-EXT-AZ:availability_zone': + 'foo-zone', + 'reservation_id': 'reservation id', + 'architecture': 'x86_64', + 'kernel_id': 'kernel id', + 'os_type': 'linux', + 'ramdisk_id': 'ramdisk id', + 'ephemeral_gb': 7, + 'root_gb': 3, + 'image': {'id': 1, + 'links': [{"rel": "bookmark", + 'href': 2}]}, + 'hostId': '1234-5678', + 'flavor': {'id': 1, + 'disk': 0, + 'ram': 512, + 'vcpus': 2}, + 'metadata': {'metering.autoscale.group': + 'X' * 512, + 'metering.ephemeral_gb': 42}} + + self.instance = FauxInstance(**self.INSTANCE_PROPERTIES) + + def test_metadata(self): + md = pollsters._get_metadata_from_object(self.instance) + for prop, value in self.INSTANCE_PROPERTIES.iteritems(): + if prop not in ("metadata"): + # Special cases + if prop == 'name': + prop = 'display_name' + elif prop == 'hostId': + prop = "host" + elif prop == 'OS-EXT-SRV-ATTR:instance_name': + prop = 'name' + self.assertEqual(md[prop], value) + user_metadata = md['user_metadata'] + expected = self.INSTANCE_PROPERTIES[ + 'metadata']['metering.autoscale.group'][:256] + self.assertEqual(user_metadata['autoscale_group'], expected) + self.assertEqual(len(user_metadata), 1) + + def test_metadata_empty_image(self): + self.INSTANCE_PROPERTIES['image'] = '' + self.instance = FauxInstance(**self.INSTANCE_PROPERTIES) + md = pollsters._get_metadata_from_object(self.instance) + self.assertEqual(md['image_ref'], None) + self.assertEqual(md['image_ref_url'], None) + + class TestPollsterBase(test_base.TestCase): def setUp(self): diff --git a/tests/image/test_notifications.py b/tests/image/test_notifications.py index 625f03dee..cd6b4877d 100644 --- a/tests/image/test_notifications.py +++ b/tests/image/test_notifications.py @@ -102,7 +102,7 @@ class TestNotification(base.TestCase): def test_image_download(self): handler = notifications.ImageDownload() - counters = handler.process_notification(NOTIFICATION_SEND) + counters = list(handler.process_notification(NOTIFICATION_SEND)) self.assertEqual(len(counters), 1) download = counters[0] self._verify_common_counter(download, 'image.download', 42) @@ -112,7 +112,7 @@ class TestNotification(base.TestCase): def test_image_serve(self): handler = notifications.ImageServe() - counters = handler.process_notification(NOTIFICATION_SEND) + counters = list(handler.process_notification(NOTIFICATION_SEND)) self.assertEqual(len(counters), 1) serve = counters[0] self._verify_common_counter(serve, 'image.serve', 42) @@ -125,7 +125,7 @@ class TestNotification(base.TestCase): def test_image_crud_on_update(self): handler = notifications.ImageCRUD() - counters = handler.process_notification(NOTIFICATION_UPDATE) + counters = list(handler.process_notification(NOTIFICATION_UPDATE)) self.assertEqual(len(counters), 1) update = counters[0] self._verify_common_counter(update, 'image.update', 1) @@ -133,7 +133,7 @@ class TestNotification(base.TestCase): def test_image_on_update(self): handler = notifications.Image() - counters = handler.process_notification(NOTIFICATION_UPDATE) + counters = list(handler.process_notification(NOTIFICATION_UPDATE)) self.assertEqual(len(counters), 1) update = counters[0] self._verify_common_counter(update, 'image', 1) @@ -141,7 +141,7 @@ class TestNotification(base.TestCase): def test_image_size_on_update(self): handler = notifications.ImageSize() - counters = handler.process_notification(NOTIFICATION_UPDATE) + counters = list(handler.process_notification(NOTIFICATION_UPDATE)) self.assertEqual(len(counters), 1) update = counters[0] self._verify_common_counter(update, 'image.size', @@ -150,7 +150,7 @@ class TestNotification(base.TestCase): def test_image_crud_on_upload(self): handler = notifications.ImageCRUD() - counters = handler.process_notification(NOTIFICATION_UPLOAD) + counters = list(handler.process_notification(NOTIFICATION_UPLOAD)) self.assertEqual(len(counters), 1) upload = counters[0] self._verify_common_counter(upload, 'image.upload', 1) @@ -158,7 +158,7 @@ class TestNotification(base.TestCase): def test_image_on_upload(self): handler = notifications.Image() - counters = handler.process_notification(NOTIFICATION_UPLOAD) + counters = list(handler.process_notification(NOTIFICATION_UPLOAD)) self.assertEqual(len(counters), 1) upload = counters[0] self._verify_common_counter(upload, 'image', 1) @@ -166,7 +166,7 @@ class TestNotification(base.TestCase): def test_image_size_on_upload(self): handler = notifications.ImageSize() - counters = handler.process_notification(NOTIFICATION_UPLOAD) + counters = list(handler.process_notification(NOTIFICATION_UPLOAD)) self.assertEqual(len(counters), 1) upload = counters[0] self._verify_common_counter(upload, 'image.size', @@ -175,7 +175,7 @@ class TestNotification(base.TestCase): def test_image_crud_on_delete(self): handler = notifications.ImageCRUD() - counters = handler.process_notification(NOTIFICATION_DELETE) + counters = list(handler.process_notification(NOTIFICATION_DELETE)) self.assertEqual(len(counters), 1) delete = counters[0] self._verify_common_counter(delete, 'image.delete', 1) @@ -183,7 +183,7 @@ class TestNotification(base.TestCase): def test_image_on_delete(self): handler = notifications.Image() - counters = handler.process_notification(NOTIFICATION_DELETE) + counters = list(handler.process_notification(NOTIFICATION_DELETE)) self.assertEqual(len(counters), 1) delete = counters[0] self._verify_common_counter(delete, 'image', 1) @@ -191,7 +191,7 @@ class TestNotification(base.TestCase): def test_image_size_on_delete(self): handler = notifications.ImageSize() - counters = handler.process_notification(NOTIFICATION_DELETE) + counters = list(handler.process_notification(NOTIFICATION_DELETE)) self.assertEqual(len(counters), 1) delete = counters[0] self._verify_common_counter(delete, 'image.size', diff --git a/tests/volume/test_notifications.py b/tests/volume/test_notifications.py index c76313e7c..aa52c4eb7 100644 --- a/tests/volume/test_notifications.py +++ b/tests/volume/test_notifications.py @@ -72,7 +72,7 @@ class TestNotifications(base.TestCase): def test_volume_exists(self): v = notifications.Volume() - counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS) + counters = list(v.process_notification(NOTIFICATION_VOLUME_EXISTS)) self.assertEqual(len(counters), 1) c = counters[0] self._verify_common_counter(c, 'volume', NOTIFICATION_VOLUME_EXISTS) @@ -80,7 +80,7 @@ class TestNotifications(base.TestCase): def test_volume_size_exists(self): v = notifications.VolumeSize() - counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS) + counters = list(v.process_notification(NOTIFICATION_VOLUME_EXISTS)) self.assertEqual(len(counters), 1) c = counters[0] self._verify_common_counter(c, 'volume.size', @@ -90,7 +90,7 @@ class TestNotifications(base.TestCase): def test_volume_delete(self): v = notifications.Volume() - counters = v.process_notification(NOTIFICATION_VOLUME_DELETE) + counters = list(v.process_notification(NOTIFICATION_VOLUME_DELETE)) self.assertEqual(len(counters), 1) c = counters[0] self._verify_common_counter(c, 'volume', NOTIFICATION_VOLUME_DELETE) @@ -98,7 +98,7 @@ class TestNotifications(base.TestCase): def test_volume_size_delete(self): v = notifications.VolumeSize() - counters = v.process_notification(NOTIFICATION_VOLUME_DELETE) + counters = list(v.process_notification(NOTIFICATION_VOLUME_DELETE)) self.assertEqual(len(counters), 1) c = counters[0] self._verify_common_counter(c, 'volume.size',