Unify Counter generation from notifications

This will make sure we don't lose any metadata information from
notifications into the Counter/samples we publish.

This is part of fixing bug #1187833 and bug #1187843

Change-Id: I315581907be1dcec33f43a5d5fd7b7876a7889f6
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2013-06-14 13:51:39 +02:00
parent bd594cbde1
commit 00531f9de0
14 changed files with 381 additions and 609 deletions

View File

@ -1,93 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
#
# 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)

View File

@ -22,10 +22,8 @@
from oslo.config import cfg from oslo.config import cfg
from ceilometer.compute import instance
from ceilometer import counter from ceilometer import counter
from ceilometer import plugin from ceilometer import plugin
from ceilometer import utils
OPTS = [ OPTS = [
@ -39,7 +37,6 @@ cfg.CONF.register_opts(OPTS)
class ComputeNotificationBase(plugin.NotificationBase): class ComputeNotificationBase(plugin.NotificationBase):
@staticmethod @staticmethod
def get_exchange_topics(conf): def get_exchange_topics(conf):
"""Return a sequence of ExchangeTopics defining the exchange and """Return a sequence of ExchangeTopics defining the exchange and
@ -54,50 +51,27 @@ class ComputeNotificationBase(plugin.NotificationBase):
class InstanceScheduled(ComputeNotificationBase): class InstanceScheduled(ComputeNotificationBase):
metadata_keys = ['request_spec']
@staticmethod @staticmethod
def get_event_types(): def get_event_types():
return ['scheduler.run_instance.scheduled'] 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): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter( name='instance.scheduled',
name='instance.scheduled', type=counter.TYPE_DELTA,
type=counter.TYPE_DELTA, volume=1,
volume=1, unit='instance',
unit='instance', user_id=None,
user_id=None, project_id=
project_id= message['payload']['request_spec']
message['payload']['request_spec'] ['instance_properties']['project_id'],
['instance_properties']['project_id'], resource_id=message['payload']['instance_id'],
resource_id=message['payload']['instance_id'], message=message)
timestamp=message['timestamp'],
resource_metadata=dict(
utils.recursive_keypairs(message['payload'])),
)
]
class ComputeInstanceNotificationBase(ComputeNotificationBase): class ComputeInstanceNotificationBase(ComputeNotificationBase):
"""Convert compute.instance.* notifications into Counters """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 @staticmethod
def get_event_types(): def get_event_types():
return ['compute.instance.create.end', return ['compute.instance.create.end',
@ -108,112 +82,83 @@ class ComputeInstanceNotificationBase(ComputeNotificationBase):
class Instance(ComputeInstanceNotificationBase): class Instance(ComputeInstanceNotificationBase):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='instance', name='instance',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='instance', unit='instance',
volume=1, volume=1,
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['instance_id'], resource_id=message['payload']['instance_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message),
),
]
class Memory(ComputeInstanceNotificationBase): class Memory(ComputeInstanceNotificationBase):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='memory', name='memory',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='MB', unit='MB',
volume=message['payload']['memory_mb'], volume=message['payload']['memory_mb'],
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['instance_id'], resource_id=message['payload']['instance_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message)),
]
class VCpus(ComputeInstanceNotificationBase): class VCpus(ComputeInstanceNotificationBase):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='vcpus', name='vcpus',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='vcpu', unit='vcpu',
volume=message['payload']['vcpus'], volume=message['payload']['vcpus'],
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['instance_id'], resource_id=message['payload']['instance_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message)),
]
class RootDiskSize(ComputeInstanceNotificationBase): class RootDiskSize(ComputeInstanceNotificationBase):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='disk.root.size', name='disk.root.size',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='GB', unit='GB',
volume=message['payload']['root_gb'], volume=message['payload']['root_gb'],
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['instance_id'], resource_id=message['payload']['instance_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message)),
]
class EphemeralDiskSize(ComputeInstanceNotificationBase): class EphemeralDiskSize(ComputeInstanceNotificationBase):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='disk.ephemeral.size', name='disk.ephemeral.size',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='GB', unit='GB',
volume=message['payload']['ephemeral_gb'], volume=message['payload']['ephemeral_gb'],
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['instance_id'], resource_id=message['payload']['instance_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message)),
]
class InstanceFlavor(ComputeInstanceNotificationBase): class InstanceFlavor(ComputeInstanceNotificationBase):
def process_notification(self, message): def process_notification(self, message):
counters = []
instance_type = message.get('payload', {}).get('instance_type') instance_type = message.get('payload', {}).get('instance_type')
if instance_type: if instance_type:
counters.append( yield counter.Counter.from_notification(
counter.Counter( name='instance:%s' % instance_type,
name='instance:%s' % instance_type, type=counter.TYPE_GAUGE,
type=counter.TYPE_GAUGE, unit='instance',
unit='instance', volume=1,
volume=1, user_id=message['payload']['user_id'],
user_id=message['payload']['user_id'], project_id=message['payload']['tenant_id'],
project_id=message['payload']['tenant_id'], resource_id=message['payload']['instance_id'],
resource_id=message['payload']['instance_id'], message=message)
timestamp=message['timestamp'],
resource_metadata=self.notification_to_metadata(
message),
)
)
return counters
class InstanceDelete(ComputeInstanceNotificationBase): class InstanceDelete(ComputeInstanceNotificationBase):
@ -226,17 +171,13 @@ class InstanceDelete(ComputeInstanceNotificationBase):
return ['compute.instance.delete.samples'] return ['compute.instance.delete.samples']
def process_notification(self, message): def process_notification(self, message):
return [ for sample in message['payload'].get('samples', []):
counter.Counter(name=sample['name'], yield counter.Counter.from_notification(
type=sample['type'], name=sample['name'],
unit=sample['unit'], type=sample['type'],
volume=sample['volume'], unit=sample['unit'],
user_id=message['payload']['user_id'], volume=sample['volume'],
project_id=message['payload']['tenant_id'], user_id=message['payload']['user_id'],
resource_id=message['payload']['instance_id'], project_id=message['payload']['tenant_id'],
timestamp=message['timestamp'], resource_id=message['payload']['instance_id'],
resource_metadata=self.notification_to_metadata( message=message)
message),
)
for sample in message['payload'].get('samples', [])
]

View File

@ -21,7 +21,8 @@
import copy import copy
import datetime import datetime
from ceilometer.compute import instance as compute_instance from oslo.config import cfg
from ceilometer.compute import plugin from ceilometer.compute import plugin
from ceilometer import counter from ceilometer import counter
from ceilometer.openstack.common import log from ceilometer.openstack.common import log
@ -30,6 +31,78 @@ from ceilometer.openstack.common import timeutils
LOG = log.getLogger(__name__) 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): def _instance_name(instance):
"""Shortcut to get instance name.""" """Shortcut to get instance name."""
return getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', None) 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, project_id=instance.tenant_id,
resource_id=instance.id, resource_id=instance.id,
timestamp=timeutils.isotime(), timestamp=timeutils.isotime(),
resource_metadata=compute_instance.get_metadata_from_object(instance), resource_metadata=_get_metadata_from_object(instance),
) )

View File

@ -23,6 +23,7 @@ in by the plugins that create them.
""" """
import collections import collections
import copy
from oslo.config import cfg from oslo.config import cfg
@ -67,3 +68,23 @@ Counter = collections.namedtuple('Counter',
TYPE_GAUGE = 'gauge' TYPE_GAUGE = 'gauge'
TYPE_DELTA = 'delta' TYPE_DELTA = 'delta'
TYPE_CUMULATIVE = 'cumulative' 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)

View File

@ -51,25 +51,6 @@ class ImageBase(plugin.NotificationBase):
class ImageCRUDBase(ImageBase): 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 @staticmethod
def get_event_types(): def get_event_types():
return [ return [
@ -80,67 +61,46 @@ class ImageCRUDBase(ImageBase):
class ImageCRUD(ImageCRUDBase): class ImageCRUD(ImageCRUDBase):
def process_notification(self, message): def process_notification(self, message):
metadata = self.notification_to_metadata(message) yield counter.Counter.from_notification(
return [ name=message['event_type'],
counter.Counter( type=counter.TYPE_DELTA,
name=message['event_type'], unit='image',
type=counter.TYPE_DELTA, volume=1,
unit='image', resource_id=message['payload']['id'],
volume=1, user_id=None,
resource_id=message['payload']['id'], project_id=message['payload']['owner'],
user_id=None, message=message)
project_id=message['payload']['owner'],
timestamp=message['timestamp'],
resource_metadata=metadata,
),
]
class Image(ImageCRUDBase): class Image(ImageCRUDBase):
def process_notification(self, message): def process_notification(self, message):
metadata = self.notification_to_metadata(message) yield counter.Counter.from_notification(
return [ name='image',
counter.Counter( type=counter.TYPE_GAUGE,
name='image', unit='image',
type=counter.TYPE_GAUGE, volume=1,
unit='image', resource_id=message['payload']['id'],
volume=1, user_id=None,
resource_id=message['payload']['id'], project_id=message['payload']['owner'],
user_id=None, message=message)
project_id=message['payload']['owner'],
timestamp=message['timestamp'],
resource_metadata=metadata,
),
]
class ImageSize(ImageCRUDBase): class ImageSize(ImageCRUDBase):
def process_notification(self, message): def process_notification(self, message):
metadata = self.notification_to_metadata(message) yield counter.Counter.from_notification(
return [ name='image.size',
counter.Counter( type=counter.TYPE_GAUGE,
name='image.size', unit='B',
type=counter.TYPE_GAUGE, volume=message['payload']['size'],
unit='B', resource_id=message['payload']['id'],
volume=message['payload']['size'], user_id=None,
resource_id=message['payload']['id'], project_id=message['payload']['owner'],
user_id=None, message=message)
project_id=message['payload']['owner'],
timestamp=message['timestamp'],
resource_metadata=metadata,
),
]
class ImageDownload(ImageBase): class ImageDownload(ImageBase):
"""Emit image_download counter when an image is downloaded.""" """Emit image_download counter when an image is downloaded."""
metadata_keys = ['destination_ip', 'owner_id']
@staticmethod @staticmethod
def get_event_types(): def get_event_types():
return [ return [
@ -148,28 +108,19 @@ class ImageDownload(ImageBase):
] ]
def process_notification(self, message): def process_notification(self, message):
metadata = self.notification_to_metadata(message) yield counter.Counter.from_notification(
return [ name='image.download',
counter.Counter( type=counter.TYPE_DELTA,
name='image.download', unit='B',
type=counter.TYPE_DELTA, volume=message['payload']['bytes_sent'],
unit='B', resource_id=message['payload']['image_id'],
volume=message['payload']['bytes_sent'], user_id=message['payload']['receiver_user_id'],
resource_id=message['payload']['image_id'], project_id=message['payload']['receiver_tenant_id'],
user_id=message['payload']['receiver_user_id'], message=message)
project_id=message['payload']['receiver_tenant_id'],
timestamp=message['timestamp'],
resource_metadata=metadata,
),
]
class ImageServe(ImageBase): class ImageServe(ImageBase):
"""Emit image_serve counter when an image is served out.""" """Emit image_serve counter when an image is served out."""
metadata_keys = ['destination_ip', 'receiver_user_id',
'receiver_tenant_id']
@staticmethod @staticmethod
def get_event_types(): def get_event_types():
return [ return [
@ -177,17 +128,12 @@ class ImageServe(ImageBase):
] ]
def process_notification(self, message): def process_notification(self, message):
metadata = self.notification_to_metadata(message) yield counter.Counter.from_notification(
return [ name='image.serve',
counter.Counter( type=counter.TYPE_DELTA,
name='image.serve', unit='B',
type=counter.TYPE_DELTA, volume=message['payload']['bytes_sent'],
unit='B', resource_id=message['payload']['image_id'],
volume=message['payload']['bytes_sent'], user_id=None,
resource_id=message['payload']['image_id'], project_id=message['payload']['owner_id'],
user_id=None, message=message)
project_id=message['payload']['owner_id'],
timestamp=message['timestamp'],
resource_metadata=metadata,
),
]

View File

@ -72,34 +72,31 @@ class NetworkNotificationBase(plugin.NotificationBase):
def process_notification(self, message): def process_notification(self, message):
LOG.info('network notification %r', message) LOG.info('network notification %r', message)
message['payload'] = message['payload'][self.resource_name] message['payload'] = message['payload'][self.resource_name]
metadata = self.notification_to_metadata(message)
counter_name = getattr(self, 'counter_name', self.resource_name) counter_name = getattr(self, 'counter_name', self.resource_name)
unit_value = getattr(self, 'unit', self.resource_name) unit_value = getattr(self, 'unit', self.resource_name)
yield counter.Counter(name=counter_name, yield counter.Counter.from_notification(
type=counter.TYPE_GAUGE, name=counter_name,
unit=unit_value, type=counter.TYPE_GAUGE,
volume=1, unit=unit_value,
user_id=message['_context_user_id'], volume=1,
project_id=message['payload']['tenant_id'], user_id=message['_context_user_id'],
resource_id=message['payload']['id'], project_id=message['payload']['tenant_id'],
timestamp=message['timestamp'], resource_id=message['payload']['id'],
resource_metadata=metadata, message=message)
)
event_type_split = message['event_type'].split('.') event_type_split = message['event_type'].split('.')
if len(event_type_split) > 2: if len(event_type_split) > 2:
yield counter.Counter(name=counter_name yield counter.Counter.from_notification(
+ "." + event_type_split[1], name=counter_name
type=counter.TYPE_DELTA, + "." + event_type_split[1],
unit=unit_value, type=counter.TYPE_DELTA,
volume=1, unit=unit_value,
user_id=message['_context_user_id'], volume=1,
project_id=message['payload']['tenant_id'], user_id=message['_context_user_id'],
resource_id=message['payload']['id'], project_id=message['payload']['tenant_id'],
timestamp=message['timestamp'], resource_id=message['payload']['id'],
resource_metadata=metadata, message=message)
)
class Network(NetworkNotificationBase): class Network(NetworkNotificationBase):
@ -107,16 +104,6 @@ class Network(NetworkNotificationBase):
metering framework. metering framework.
""" """
metadata_keys = [
"status",
"subnets",
"name",
"router:external",
"admin_state_up",
"shared",
]
resource_name = 'network' resource_name = 'network'
@ -125,19 +112,6 @@ class Subnet(NetworkNotificationBase):
metering framework. metering framework.
""" """
metadata_keys = [
"name",
"enable_dhcp",
"network_id",
"dns_nameservers",
"allocation_pools",
"host_routes",
"ip_version",
"gateway_ip",
"cidr",
]
resource_name = 'subnet' resource_name = 'subnet'
@ -146,18 +120,6 @@ class Port(NetworkNotificationBase):
metering framework. metering framework.
""" """
metadata_keys = [
"status",
"name",
"admin_state_up",
"network_id",
"device_owner",
"mac_address",
"fixed_ips",
"device_id",
]
resource_name = 'port' resource_name = 'port'
@ -166,14 +128,6 @@ class Router(NetworkNotificationBase):
metering framework. metering framework.
""" """
metadata_keys = [
"status",
"external_gateway_info",
"admin_state_up",
"name",
]
resource_name = 'router' resource_name = 'router'
@ -182,15 +136,6 @@ class FloatingIP(NetworkNotificationBase):
metering framework. metering framework.
""" """
metadata_keys = [
"router_id",
"floating_network_id",
"fixed_ip_address",
"floating_ip_address",
"port_id",
]
resource_name = 'floatingip' resource_name = 'floatingip'
counter_name = 'ip.floating' counter_name = 'ip.floating'
unit = 'ip' unit = 'ip'

View File

@ -69,14 +69,6 @@ class NotificationBase(PluginBase):
:param message: Message to process. :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): class PollsterBase(PluginBase):
"""Base class for plugins that support the polling API.""" """Base class for plugins that support the polling API."""

View File

@ -36,15 +36,7 @@ cfg.CONF.register_opts(OPTS)
class _Base(plugin.NotificationBase): class _Base(plugin.NotificationBase):
"""Convert volume notifications into Counters """Convert volume notifications into Counters."""
"""
metadata_keys = [
"status",
"display_name",
"volume_type",
"size",
]
@staticmethod @staticmethod
def get_exchange_topics(conf): def get_exchange_topics(conf):
@ -66,36 +58,26 @@ class _Base(plugin.NotificationBase):
class Volume(_Base): class Volume(_Base):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='volume', name='volume',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='volume', unit='volume',
volume=1, volume=1,
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['volume_id'], resource_id=message['payload']['volume_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message),
),
]
class VolumeSize(_Base): class VolumeSize(_Base):
def process_notification(self, message): def process_notification(self, message):
return [ yield counter.Counter.from_notification(
counter.Counter(name='volume.size', name='volume.size',
type=counter.TYPE_GAUGE, type=counter.TYPE_GAUGE,
unit='GB', unit='GB',
volume=message['payload']['size'], volume=message['payload']['size'],
user_id=message['payload']['user_id'], user_id=message['payload']['user_id'],
project_id=message['payload']['tenant_id'], project_id=message['payload']['tenant_id'],
resource_id=message['payload']['volume_id'], resource_id=message['payload']['volume_id'],
timestamp=message['timestamp'], message=message)
resource_metadata=self.notification_to_metadata(
message),
),
]

View File

@ -28,18 +28,6 @@
#enable_v1_api=true #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 # Options defined in ceilometer.compute.notifications
# #
@ -48,6 +36,18 @@
#nova_control_exchange=nova #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 # Options defined in ceilometer.compute.virt.inspector
# #

View File

@ -1,112 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
#
# 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)

View File

@ -401,9 +401,9 @@ INSTANCE_SCHEDULED = {
class TestNotifications(base.TestCase): class TestNotifications(base.TestCase):
def test_process_notification(self): def test_process_notification(self):
info = notifications.Instance().process_notification( info = list(notifications.Instance().process_notification(
INSTANCE_CREATE_END INSTANCE_CREATE_END
)[0] ))[0]
for name, actual, expected in [ for name, actual, expected in [
('counter_name', info.name, 'instance'), ('counter_name', info.name, 'instance'),
('counter_type', info.type, counter.TYPE_GAUGE), ('counter_type', info.type, counter.TYPE_GAUGE),
@ -412,7 +412,8 @@ class TestNotifications(base.TestCase):
INSTANCE_CREATE_END['timestamp']), INSTANCE_CREATE_END['timestamp']),
('resource_id', info.resource_id, ('resource_id', info.resource_id,
INSTANCE_CREATE_END['payload']['instance_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']), INSTANCE_CREATE_END['payload']['instance_type_id']),
('host', info.resource_metadata['host'], ('host', info.resource_metadata['host'],
INSTANCE_CREATE_END['publisher_id']), INSTANCE_CREATE_END['publisher_id']),
@ -425,42 +426,42 @@ class TestNotifications(base.TestCase):
def test_instance_create_instance(self): def test_instance_create_instance(self):
ic = notifications.Instance() ic = notifications.Instance()
counters = ic.process_notification(INSTANCE_CREATE_END) counters = list(ic.process_notification(INSTANCE_CREATE_END))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, 1) self.assertEqual(c.volume, 1)
def test_instance_create_flavor(self): def test_instance_create_flavor(self):
ic = notifications.InstanceFlavor() ic = notifications.InstanceFlavor()
counters = ic.process_notification(INSTANCE_CREATE_END) counters = list(ic.process_notification(INSTANCE_CREATE_END))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, 1) self.assertEqual(c.volume, 1)
def test_instance_create_memory(self): def test_instance_create_memory(self):
ic = notifications.Memory() ic = notifications.Memory()
counters = ic.process_notification(INSTANCE_CREATE_END) counters = list(ic.process_notification(INSTANCE_CREATE_END))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['memory_mb']) self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['memory_mb'])
def test_instance_create_vcpus(self): def test_instance_create_vcpus(self):
ic = notifications.VCpus() ic = notifications.VCpus()
counters = ic.process_notification(INSTANCE_CREATE_END) counters = list(ic.process_notification(INSTANCE_CREATE_END))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['vcpus']) self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['vcpus'])
def test_instance_create_root_disk_size(self): def test_instance_create_root_disk_size(self):
ic = notifications.RootDiskSize() ic = notifications.RootDiskSize()
counters = ic.process_notification(INSTANCE_CREATE_END) counters = list(ic.process_notification(INSTANCE_CREATE_END))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['root_gb']) self.assertEqual(c.volume, INSTANCE_CREATE_END['payload']['root_gb'])
def test_instance_create_ephemeral_disk_size(self): def test_instance_create_ephemeral_disk_size(self):
ic = notifications.EphemeralDiskSize() ic = notifications.EphemeralDiskSize()
counters = ic.process_notification(INSTANCE_CREATE_END) counters = list(ic.process_notification(INSTANCE_CREATE_END))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, self.assertEqual(c.volume,
@ -468,34 +469,34 @@ class TestNotifications(base.TestCase):
def test_instance_exists_instance(self): def test_instance_exists_instance(self):
ic = notifications.Instance() ic = notifications.Instance()
counters = ic.process_notification(INSTANCE_EXISTS) counters = list(ic.process_notification(INSTANCE_EXISTS))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
def test_instance_exists_flavor(self): def test_instance_exists_flavor(self):
ic = notifications.Instance() ic = notifications.Instance()
counters = ic.process_notification(INSTANCE_EXISTS) counters = list(ic.process_notification(INSTANCE_EXISTS))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
def test_instance_delete_instance(self): def test_instance_delete_instance(self):
ic = notifications.Instance() ic = notifications.Instance()
counters = ic.process_notification(INSTANCE_DELETE_START) counters = list(ic.process_notification(INSTANCE_DELETE_START))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
def test_instance_delete_flavor(self): def test_instance_delete_flavor(self):
ic = notifications.Instance() ic = notifications.Instance()
counters = ic.process_notification(INSTANCE_DELETE_START) counters = list(ic.process_notification(INSTANCE_DELETE_START))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
def test_instance_finish_resize_instance(self): def test_instance_finish_resize_instance(self):
ic = notifications.Instance() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, 1) self.assertEqual(c.volume, 1)
def test_instance_finish_resize_flavor(self): def test_instance_finish_resize_flavor(self):
ic = notifications.InstanceFlavor() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, 1) self.assertEqual(c.volume, 1)
@ -503,7 +504,7 @@ class TestNotifications(base.TestCase):
def test_instance_finish_resize_memory(self): def test_instance_finish_resize_memory(self):
ic = notifications.Memory() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, self.assertEqual(c.volume,
@ -511,7 +512,7 @@ class TestNotifications(base.TestCase):
def test_instance_finish_resize_vcpus(self): def test_instance_finish_resize_vcpus(self):
ic = notifications.VCpus() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, self.assertEqual(c.volume,
@ -519,14 +520,14 @@ class TestNotifications(base.TestCase):
def test_instance_resize_finish_instance(self): def test_instance_resize_finish_instance(self):
ic = notifications.Instance() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, 1) self.assertEqual(c.volume, 1)
def test_instance_resize_finish_flavor(self): def test_instance_resize_finish_flavor(self):
ic = notifications.InstanceFlavor() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, 1) self.assertEqual(c.volume, 1)
@ -534,7 +535,7 @@ class TestNotifications(base.TestCase):
def test_instance_resize_finish_memory(self): def test_instance_resize_finish_memory(self):
ic = notifications.Memory() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, self.assertEqual(c.volume,
@ -542,7 +543,7 @@ class TestNotifications(base.TestCase):
def test_instance_resize_finish_vcpus(self): def test_instance_resize_finish_vcpus(self):
ic = notifications.VCpus() 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) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self.assertEqual(c.volume, self.assertEqual(c.volume,
@ -550,7 +551,7 @@ class TestNotifications(base.TestCase):
def test_instance_delete_samples(self): def test_instance_delete_samples(self):
ic = notifications.InstanceDelete() ic = notifications.InstanceDelete()
counters = ic.process_notification(INSTANCE_DELETE_SAMPLES) counters = list(ic.process_notification(INSTANCE_DELETE_SAMPLES))
self.assertEqual(len(counters), 2) self.assertEqual(len(counters), 2)
names = [c.name for c in counters] names = [c.name for c in counters]
self.assertEqual(names, ['sample-name1', 'sample-name2']) self.assertEqual(names, ['sample-name1', 'sample-name2'])
@ -561,7 +562,7 @@ class TestNotifications(base.TestCase):
self.assertIn(INSTANCE_SCHEDULED['event_type'], self.assertIn(INSTANCE_SCHEDULED['event_type'],
ic.get_event_types()) ic.get_event_types())
counters = ic.process_notification(INSTANCE_SCHEDULED) counters = list(ic.process_notification(INSTANCE_SCHEDULED))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
names = [c.name for c in counters] names = [c.name for c in counters]
self.assertEqual(names, ['instance.scheduled']) self.assertEqual(names, ['instance.scheduled'])

View File

@ -29,6 +29,82 @@ from ceilometer.compute.virt import inspector as virt_inspector
from ceilometer.tests import base as test_base 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): class TestPollsterBase(test_base.TestCase):
def setUp(self): def setUp(self):

View File

@ -102,7 +102,7 @@ class TestNotification(base.TestCase):
def test_image_download(self): def test_image_download(self):
handler = notifications.ImageDownload() handler = notifications.ImageDownload()
counters = handler.process_notification(NOTIFICATION_SEND) counters = list(handler.process_notification(NOTIFICATION_SEND))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
download = counters[0] download = counters[0]
self._verify_common_counter(download, 'image.download', 42) self._verify_common_counter(download, 'image.download', 42)
@ -112,7 +112,7 @@ class TestNotification(base.TestCase):
def test_image_serve(self): def test_image_serve(self):
handler = notifications.ImageServe() handler = notifications.ImageServe()
counters = handler.process_notification(NOTIFICATION_SEND) counters = list(handler.process_notification(NOTIFICATION_SEND))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
serve = counters[0] serve = counters[0]
self._verify_common_counter(serve, 'image.serve', 42) self._verify_common_counter(serve, 'image.serve', 42)
@ -125,7 +125,7 @@ class TestNotification(base.TestCase):
def test_image_crud_on_update(self): def test_image_crud_on_update(self):
handler = notifications.ImageCRUD() handler = notifications.ImageCRUD()
counters = handler.process_notification(NOTIFICATION_UPDATE) counters = list(handler.process_notification(NOTIFICATION_UPDATE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
update = counters[0] update = counters[0]
self._verify_common_counter(update, 'image.update', 1) self._verify_common_counter(update, 'image.update', 1)
@ -133,7 +133,7 @@ class TestNotification(base.TestCase):
def test_image_on_update(self): def test_image_on_update(self):
handler = notifications.Image() handler = notifications.Image()
counters = handler.process_notification(NOTIFICATION_UPDATE) counters = list(handler.process_notification(NOTIFICATION_UPDATE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
update = counters[0] update = counters[0]
self._verify_common_counter(update, 'image', 1) self._verify_common_counter(update, 'image', 1)
@ -141,7 +141,7 @@ class TestNotification(base.TestCase):
def test_image_size_on_update(self): def test_image_size_on_update(self):
handler = notifications.ImageSize() handler = notifications.ImageSize()
counters = handler.process_notification(NOTIFICATION_UPDATE) counters = list(handler.process_notification(NOTIFICATION_UPDATE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
update = counters[0] update = counters[0]
self._verify_common_counter(update, 'image.size', self._verify_common_counter(update, 'image.size',
@ -150,7 +150,7 @@ class TestNotification(base.TestCase):
def test_image_crud_on_upload(self): def test_image_crud_on_upload(self):
handler = notifications.ImageCRUD() handler = notifications.ImageCRUD()
counters = handler.process_notification(NOTIFICATION_UPLOAD) counters = list(handler.process_notification(NOTIFICATION_UPLOAD))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
upload = counters[0] upload = counters[0]
self._verify_common_counter(upload, 'image.upload', 1) self._verify_common_counter(upload, 'image.upload', 1)
@ -158,7 +158,7 @@ class TestNotification(base.TestCase):
def test_image_on_upload(self): def test_image_on_upload(self):
handler = notifications.Image() handler = notifications.Image()
counters = handler.process_notification(NOTIFICATION_UPLOAD) counters = list(handler.process_notification(NOTIFICATION_UPLOAD))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
upload = counters[0] upload = counters[0]
self._verify_common_counter(upload, 'image', 1) self._verify_common_counter(upload, 'image', 1)
@ -166,7 +166,7 @@ class TestNotification(base.TestCase):
def test_image_size_on_upload(self): def test_image_size_on_upload(self):
handler = notifications.ImageSize() handler = notifications.ImageSize()
counters = handler.process_notification(NOTIFICATION_UPLOAD) counters = list(handler.process_notification(NOTIFICATION_UPLOAD))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
upload = counters[0] upload = counters[0]
self._verify_common_counter(upload, 'image.size', self._verify_common_counter(upload, 'image.size',
@ -175,7 +175,7 @@ class TestNotification(base.TestCase):
def test_image_crud_on_delete(self): def test_image_crud_on_delete(self):
handler = notifications.ImageCRUD() handler = notifications.ImageCRUD()
counters = handler.process_notification(NOTIFICATION_DELETE) counters = list(handler.process_notification(NOTIFICATION_DELETE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
delete = counters[0] delete = counters[0]
self._verify_common_counter(delete, 'image.delete', 1) self._verify_common_counter(delete, 'image.delete', 1)
@ -183,7 +183,7 @@ class TestNotification(base.TestCase):
def test_image_on_delete(self): def test_image_on_delete(self):
handler = notifications.Image() handler = notifications.Image()
counters = handler.process_notification(NOTIFICATION_DELETE) counters = list(handler.process_notification(NOTIFICATION_DELETE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
delete = counters[0] delete = counters[0]
self._verify_common_counter(delete, 'image', 1) self._verify_common_counter(delete, 'image', 1)
@ -191,7 +191,7 @@ class TestNotification(base.TestCase):
def test_image_size_on_delete(self): def test_image_size_on_delete(self):
handler = notifications.ImageSize() handler = notifications.ImageSize()
counters = handler.process_notification(NOTIFICATION_DELETE) counters = list(handler.process_notification(NOTIFICATION_DELETE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
delete = counters[0] delete = counters[0]
self._verify_common_counter(delete, 'image.size', self._verify_common_counter(delete, 'image.size',

View File

@ -72,7 +72,7 @@ class TestNotifications(base.TestCase):
def test_volume_exists(self): def test_volume_exists(self):
v = notifications.Volume() v = notifications.Volume()
counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS) counters = list(v.process_notification(NOTIFICATION_VOLUME_EXISTS))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self._verify_common_counter(c, 'volume', NOTIFICATION_VOLUME_EXISTS) self._verify_common_counter(c, 'volume', NOTIFICATION_VOLUME_EXISTS)
@ -80,7 +80,7 @@ class TestNotifications(base.TestCase):
def test_volume_size_exists(self): def test_volume_size_exists(self):
v = notifications.VolumeSize() v = notifications.VolumeSize()
counters = v.process_notification(NOTIFICATION_VOLUME_EXISTS) counters = list(v.process_notification(NOTIFICATION_VOLUME_EXISTS))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self._verify_common_counter(c, 'volume.size', self._verify_common_counter(c, 'volume.size',
@ -90,7 +90,7 @@ class TestNotifications(base.TestCase):
def test_volume_delete(self): def test_volume_delete(self):
v = notifications.Volume() v = notifications.Volume()
counters = v.process_notification(NOTIFICATION_VOLUME_DELETE) counters = list(v.process_notification(NOTIFICATION_VOLUME_DELETE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self._verify_common_counter(c, 'volume', NOTIFICATION_VOLUME_DELETE) self._verify_common_counter(c, 'volume', NOTIFICATION_VOLUME_DELETE)
@ -98,7 +98,7 @@ class TestNotifications(base.TestCase):
def test_volume_size_delete(self): def test_volume_size_delete(self):
v = notifications.VolumeSize() v = notifications.VolumeSize()
counters = v.process_notification(NOTIFICATION_VOLUME_DELETE) counters = list(v.process_notification(NOTIFICATION_VOLUME_DELETE))
self.assertEqual(len(counters), 1) self.assertEqual(len(counters), 1)
c = counters[0] c = counters[0]
self._verify_common_counter(c, 'volume.size', self._verify_common_counter(c, 'volume.size',