image: add update event, fix ImageServe owner
This adds handling of image.update events and create 2 counters for it: Image, counting images, and ImageSize, counting images size. This fixes bug #1056981. This also fixes ImageServe owner which was set wrongly to user rather than project, and fixes counter type for ImageServe and ImageDownload to delta. Change-Id: I2512cdfc37f17c425f49a5e5d6d2e25ccb59a3ca Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
a725f64f3c
commit
7873fd8bfd
|
@ -109,7 +109,7 @@ class ImageSizePollster(_Base):
|
|||
for image in self.iter_images():
|
||||
yield counter.Counter(
|
||||
source='?',
|
||||
name='image_size',
|
||||
name='image.size',
|
||||
type=counter.TYPE_GAUGE,
|
||||
volume=image['size'],
|
||||
user_id=None,
|
||||
|
|
|
@ -41,10 +41,6 @@ class ImageBase(plugin.NotificationBase):
|
|||
the metering framework.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_event_types():
|
||||
return ['image.send']
|
||||
|
||||
@staticmethod
|
||||
def get_exchange_topics(conf):
|
||||
"""Return a sequence of ExchangeTopics defining the exchange and
|
||||
|
@ -56,19 +52,89 @@ class ImageBase(plugin.NotificationBase):
|
|||
for topic in conf.notification_topics)),
|
||||
]
|
||||
|
||||
def _counter(self, message, name, user_id, project_id):
|
||||
|
||||
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 [
|
||||
'image.update',
|
||||
]
|
||||
|
||||
|
||||
class ImageCRUD(ImageCRUDBase):
|
||||
|
||||
def process_notification(self, message):
|
||||
metadata = self.notification_to_metadata(message)
|
||||
return counter.Counter(
|
||||
return [
|
||||
counter.Counter(
|
||||
source='?',
|
||||
name=name,
|
||||
type=counter.TYPE_GAUGE,
|
||||
volume=message['payload']['bytes_sent'],
|
||||
resource_id=message['payload']['image_id'],
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
name=message['event_type'],
|
||||
type=counter.TYPE_DELTA,
|
||||
volume=1,
|
||||
resource_id=message['payload']['id'],
|
||||
user_id=None,
|
||||
project_id=message['payload']['owner'],
|
||||
timestamp=message['timestamp'],
|
||||
resource_metadata=metadata,
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class Image(ImageCRUDBase):
|
||||
|
||||
def process_notification(self, message):
|
||||
metadata = self.notification_to_metadata(message)
|
||||
return [
|
||||
counter.Counter(
|
||||
source='?',
|
||||
name='image',
|
||||
type=counter.TYPE_GAUGE,
|
||||
volume=1,
|
||||
resource_id=message['payload']['id'],
|
||||
user_id=None,
|
||||
project_id=message['payload']['owner'],
|
||||
timestamp=message['timestamp'],
|
||||
resource_metadata=metadata,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class ImageSize(ImageCRUDBase):
|
||||
|
||||
def process_notification(self, message):
|
||||
metadata = self.notification_to_metadata(message)
|
||||
return [
|
||||
counter.Counter(
|
||||
source='?',
|
||||
name='image.size',
|
||||
type=counter.TYPE_GAUGE,
|
||||
volume=message['payload']['size'],
|
||||
resource_id=message['payload']['id'],
|
||||
user_id=None,
|
||||
project_id=message['payload']['owner'],
|
||||
timestamp=message['timestamp'],
|
||||
resource_metadata=metadata,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class ImageDownload(ImageBase):
|
||||
|
@ -76,13 +142,27 @@ class ImageDownload(ImageBase):
|
|||
|
||||
metadata_keys = ['destination_ip', 'owner_id']
|
||||
|
||||
def process_notification(self, message):
|
||||
@staticmethod
|
||||
def get_event_types():
|
||||
return [
|
||||
self._counter(message,
|
||||
'image_download',
|
||||
message['payload']['receiver_user_id'],
|
||||
message['payload']['receiver_tenant_id']),
|
||||
]
|
||||
'image.send',
|
||||
]
|
||||
|
||||
def process_notification(self, message):
|
||||
metadata = self.notification_to_metadata(message)
|
||||
return [
|
||||
counter.Counter(
|
||||
source='?',
|
||||
name='image.download',
|
||||
type=counter.TYPE_DELTA,
|
||||
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,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class ImageServe(ImageBase):
|
||||
|
@ -91,10 +171,24 @@ class ImageServe(ImageBase):
|
|||
metadata_keys = ['destination_ip', 'receiver_user_id',
|
||||
'receiver_tenant_id']
|
||||
|
||||
def process_notification(self, message):
|
||||
@staticmethod
|
||||
def get_event_types():
|
||||
return [
|
||||
self._counter(message,
|
||||
'image_serve',
|
||||
message['payload']['owner_id'],
|
||||
None),
|
||||
]
|
||||
'image.send',
|
||||
]
|
||||
|
||||
def process_notification(self, message):
|
||||
metadata = self.notification_to_metadata(message)
|
||||
return [
|
||||
counter.Counter(
|
||||
source='?',
|
||||
name='image.serve',
|
||||
type=counter.TYPE_DELTA,
|
||||
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,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -61,6 +61,10 @@ ceilometer::
|
|||
# Enable the ceilometer services
|
||||
enable_service ceilometer-acompute,ceilometer-acentral,ceilometer-collector,ceilometer-api
|
||||
|
||||
5. If you want to be able to retrieve image counters, you need to instruct
|
||||
Glance to send notifications to the bus by changing ``notifier_strategy``
|
||||
to ``rabbit`` in ``glance-api.conf``.
|
||||
|
||||
Installing Manually
|
||||
+++++++++++++++++++
|
||||
|
||||
|
|
|
@ -82,9 +82,10 @@ Image (Glance)
|
|||
Name Type Volume Resource Note
|
||||
======================== ========== ======= ======== =======================================================
|
||||
image Gauge 1 image ID Image polling -> it (still) exists
|
||||
image_size Gauge bytes image ID Uploaded image size
|
||||
image_download Gauge bytes image ID Image is downloaded
|
||||
image_serve Gauge bytes image ID Image is served out
|
||||
image.size Gauge bytes image ID Uploaded image size
|
||||
image.update Delta reqs image ID Number of update on the image
|
||||
image.download Delta bytes image ID Image is downloaded
|
||||
image.serve Delta bytes image ID Image is served out
|
||||
======================== ========== ======= ======== =======================================================
|
||||
|
||||
Volume (Cinder)
|
||||
|
|
3
setup.py
3
setup.py
|
@ -55,6 +55,9 @@ setuptools.setup(
|
|||
ephemeral_disk_size = ceilometer.compute.notifications:EphemeralDiskSize
|
||||
volume = ceilometer.volume.notifications:Volume
|
||||
volume_size = ceilometer.volume.notifications:VolumeSize
|
||||
image_crud = ceilometer.image.notifications:ImageCRUD
|
||||
image = ceilometer.image.notifications:Image
|
||||
image_size = ceilometer.image.notifications:ImageSize
|
||||
image_download = ceilometer.image.notifications:ImageDownload
|
||||
image_serve = ceilometer.image.notifications:ImageServe
|
||||
network = ceilometer.network.notifications:Network
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# Copyright © 2012 Red Hat Inc.
|
||||
#
|
||||
# Author: Eoghan Glynn <eglynn@redhat.com>
|
||||
# Author: Julien danjou <julien@danjou.info>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
|
@ -25,7 +26,7 @@ from tests import utils
|
|||
|
||||
NOW = datetime.isoformat(datetime.utcnow())
|
||||
|
||||
NOTIFICATION_IMAGE_SEND = {
|
||||
NOTIFICATION_SEND = {
|
||||
u'event_type': u'image.send',
|
||||
u'timestamp': NOW,
|
||||
u'message_id': utils.fake_uuid('a'),
|
||||
|
@ -39,40 +40,90 @@ NOTIFICATION_IMAGE_SEND = {
|
|||
u'owner_id': utils.fake_uuid('e')}
|
||||
}
|
||||
|
||||
IMAGE_META = {u'status': u'saving',
|
||||
u'name': u'fake image #3',
|
||||
u'deleted': False,
|
||||
u'container_format': u'ovf',
|
||||
u'created_at': u'2012-09-18T10:13:44.571370',
|
||||
u'disk_format': u'vhd',
|
||||
u'updated_at': u'2012-09-18T10:13:44.623120',
|
||||
u'properties': {u'key2': u'value2',
|
||||
u'key1': u'value1'},
|
||||
u'min_disk': 0,
|
||||
u'protected': False,
|
||||
u'id': utils.fake_uuid('c'),
|
||||
u'location': None,
|
||||
u'checksum': u'd990432ef91afef3ad9dbf4a975d3365',
|
||||
u'owner': "fake",
|
||||
u'is_public': False,
|
||||
u'deleted_at': None,
|
||||
u'min_ram': 0,
|
||||
u'size': 19}
|
||||
|
||||
|
||||
NOTIFICATION_UPDATE = {"message_id": "0c65cb9c-018c-11e2-bc91-5453ed1bbb5f",
|
||||
"publisher_id": "images.example.com",
|
||||
"event_type": "image.update",
|
||||
"priority": "info",
|
||||
"payload": IMAGE_META,
|
||||
"timestamp": NOW}
|
||||
|
||||
|
||||
class TestNotification(unittest.TestCase):
|
||||
|
||||
def _verify_common_counter(self, c, name):
|
||||
def _verify_common_counter(self, c, name, volume):
|
||||
self.assertFalse(c is None)
|
||||
self.assertEqual(c.name, name)
|
||||
self.assertEqual(c.type, counter.TYPE_GAUGE)
|
||||
self.assertEqual(c.volume, 42)
|
||||
self.assertEqual(c.resource_id, utils.fake_uuid('c'))
|
||||
self.assertEqual(c.timestamp, NOW)
|
||||
self.assertEqual(c.volume, volume)
|
||||
metadata = c.resource_metadata
|
||||
self.assertEquals(metadata.get('event_type'), u'image.send')
|
||||
self.assertEquals(metadata.get('host'), u'images.example.com')
|
||||
self.assertEquals(metadata.get('destination_ip'), u'1.2.3.4')
|
||||
|
||||
def test_image_download(self):
|
||||
handler = notifications.ImageDownload()
|
||||
counters = handler.process_notification(NOTIFICATION_IMAGE_SEND)
|
||||
counters = handler.process_notification(NOTIFICATION_SEND)
|
||||
self.assertEqual(len(counters), 1)
|
||||
download = counters[0]
|
||||
self._verify_common_counter(download, 'image_download')
|
||||
self._verify_common_counter(download, 'image.download', 42)
|
||||
self.assertEqual(download.user_id, utils.fake_uuid('d'))
|
||||
self.assertEqual(download.project_id, utils.fake_uuid('b'))
|
||||
self.assertEquals(download.resource_metadata.get('owner_id'),
|
||||
utils.fake_uuid('e'))
|
||||
self.assertEqual(download.type, counter.TYPE_DELTA)
|
||||
|
||||
def test_image_serve(self):
|
||||
handler = notifications.ImageServe()
|
||||
counters = handler.process_notification(NOTIFICATION_IMAGE_SEND)
|
||||
counters = handler.process_notification(NOTIFICATION_SEND)
|
||||
self.assertEqual(len(counters), 1)
|
||||
serve = counters[0]
|
||||
self._verify_common_counter(serve, 'image_serve')
|
||||
self.assertEqual(serve.user_id, utils.fake_uuid('e'))
|
||||
self._verify_common_counter(serve, 'image.serve', 42)
|
||||
self.assertEqual(serve.project_id, utils.fake_uuid('e'))
|
||||
self.assertEquals(serve.resource_metadata.get('receiver_user_id'),
|
||||
utils.fake_uuid('d'))
|
||||
self.assertEquals(serve.resource_metadata.get('receiver_tenant_id'),
|
||||
utils.fake_uuid('b'))
|
||||
self.assertEqual(serve.type, counter.TYPE_DELTA)
|
||||
|
||||
def test_image_crud_on_update(self):
|
||||
handler = notifications.ImageCRUD()
|
||||
counters = handler.process_notification(NOTIFICATION_UPDATE)
|
||||
self.assertEqual(len(counters), 1)
|
||||
update = counters[0]
|
||||
self._verify_common_counter(update, 'image.update', 1)
|
||||
self.assertEqual(update.type, counter.TYPE_DELTA)
|
||||
|
||||
def test_image_on_update(self):
|
||||
handler = notifications.Image()
|
||||
counters = handler.process_notification(NOTIFICATION_UPDATE)
|
||||
self.assertEqual(len(counters), 1)
|
||||
update = counters[0]
|
||||
self._verify_common_counter(update, 'image', 1)
|
||||
self.assertEqual(update.type, counter.TYPE_GAUGE)
|
||||
|
||||
def test_image_size_on_update(self):
|
||||
handler = notifications.ImageSize()
|
||||
counters = handler.process_notification(NOTIFICATION_UPDATE)
|
||||
self.assertEqual(len(counters), 1)
|
||||
update = counters[0]
|
||||
self._verify_common_counter(update, 'image.size',
|
||||
IMAGE_META['size'])
|
||||
self.assertEqual(update.type, counter.TYPE_GAUGE)
|
||||
|
|
Loading…
Reference in New Issue