From 4a1f5c7440aada258ab9e703e78bc405752a5aad Mon Sep 17 00:00:00 2001 From: "Mark J. Washenberger" Date: Wed, 14 Nov 2012 11:40:45 -0800 Subject: [PATCH] Add an image repo proxy that handles notifications This patch hides image notifications inside the the domain layer. This way, eventually the controller won't have to keep track of notifications. Part of implementing bp:glance-domain-logic-layer Change-Id: Ie763a50ea416cae66b8015162dcdb5232a4e0a1d --- glance/notifier/__init__.py | 52 ++++++++++++++++++++++++++ glance/tests/unit/test_notifier.py | 59 ++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/glance/notifier/__init__.py b/glance/notifier/__init__.py index e3a791a5d0..cb63117622 100644 --- a/glance/notifier/__init__.py +++ b/glance/notifier/__init__.py @@ -20,6 +20,7 @@ import socket import uuid from glance.common import exception +import glance.domain from glance.openstack.common import cfg from glance.openstack.common import importutils import glance.openstack.common.log as logging @@ -85,3 +86,54 @@ class Notifier(object): def error(self, event_type, payload): msg = self.generate_message(event_type, "ERROR", payload) self.strategy.error(msg) + + +def format_image_notification(image): + """ + Given a glance.domain.Image object, return a dictionary of relevant + notification information. + """ + return { + 'id': image.image_id, + 'name': image.name, + 'status': image.status, + 'created_at': timeutils.isotime(image.created_at), + 'updated_at': timeutils.isotime(image.updated_at), + 'min_disk': image.min_disk, + 'min_ram': image.min_ram, + 'protected': image.protected, + 'location': image.location, + 'checksum': image.checksum, + 'owner': image.owner, + 'disk_format': image.disk_format, + 'container_format': image.container_format, + 'size': image.size, + 'is_public': image.visibility == 'public', + 'properties': dict(image.extra_properties), + 'tags': list(image.tags), + 'deleted': False, + 'deleted_at': None, + } + + +class ImageRepoProxy(glance.domain.ImageRepoProxy): + + def __init__(self, image_repo, notifier): + self.image_repo = image_repo + self.notifier = notifier + super(ImageRepoProxy, self).__init__(image_repo) + + def save(self, image): + self.image_repo.save(image) + self.notifier.info('image.update', format_image_notification(image)) + + def add(self, image): + self.image_repo.add(image) + self.notifier.info('image.update', format_image_notification(image)) + + def remove(self, image): + self.image_repo.remove(image) + payload = format_image_notification(image) + payload['deleted'] = True + payload['deleted_at'] = timeutils.isotime() + self.notifier.info('image.delete', payload) diff --git a/glance/tests/unit/test_notifier.py b/glance/tests/unit/test_notifier.py index f92be805ef..d43515ed01 100644 --- a/glance/tests/unit/test_notifier.py +++ b/glance/tests/unit/test_notifier.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime import kombu.entity import mox try: @@ -30,6 +31,25 @@ import glance.notifier.notify_kombu from glance.openstack.common import importutils import glance.openstack.common.log as logging from glance.tests import utils +import glance.tests.unit.utils as unit_test_utils + + +DATETIME = datetime.datetime(2012, 5, 16, 15, 27, 36, 325355) + + +UUID1 = 'c80a1a6c-bd1f-41c5-90ee-81afedb1d58d' +TENANT1 = '6838eb7b-6ded-434a-882c-b344c77fe8df' + + +class ImageRepoStub(object): + def remove(self, *args, **kwargs): + return 'image_from_get' + + def save(self, *args, **kwargs): + return 'image_from_save' + + def add(self, *args, **kwargs): + return 'image_from_add' class TestNotifier(utils.BaseTestCase): @@ -406,3 +426,42 @@ class TestRabbitContentType(utils.BaseTestCase): def test_content_type_passed(self): self.notifier.warn("test_event", "test_message") self.assertEquals(self.called['content_type'], 'application/json') + + +class TestImageNotifications(utils.BaseTestCase): + """Test Image Notifications work""" + + def setUp(self): + self.image = glance.domain.Image( + image_id=UUID1, name='image-1', status='active', size=1024, + created_at=DATETIME, updated_at=DATETIME, owner=TENANT1, + visibility='public', container_format='ami', + tags=['one', 'two'], disk_format='ami', min_ram=128, + min_disk=10, checksum='ca425b88f047ce8ec45ee90e813ada91') + self.image_repo_stub = ImageRepoStub() + self.notifier = unit_test_utils.FakeNotifier() + self.image_repo_proxy = glance.notifier.ImageRepoProxy( + self.image_repo_stub, self.notifier) + super(TestImageNotifications, self).setUp() + + def test_image_save_notification(self): + self.image_repo_proxy.save(self.image) + output_log = self.notifier.get_log() + self.assertEqual(output_log['notification_type'], 'INFO') + self.assertEqual(output_log['event_type'], 'image.update') + self.assertEqual(output_log['payload']['id'], self.image.image_id) + + def test_image_add_notification(self): + self.image_repo_proxy.add(self.image) + output_log = self.notifier.get_log() + self.assertEqual(output_log['notification_type'], 'INFO') + self.assertEqual(output_log['event_type'], 'image.update') + self.assertEqual(output_log['payload']['id'], self.image.image_id) + + def test_image_delete_notification(self): + self.image_repo_proxy.remove(self.image) + output_log = self.notifier.get_log() + self.assertEqual(output_log['notification_type'], 'INFO') + self.assertEqual(output_log['event_type'], 'image.delete') + self.assertEqual(output_log['payload']['id'], self.image.image_id) + self.assertTrue(output_log['payload']['deleted'])