Adds notifications for images v2

The v2 API didnt generate any notifications. It should
send same as those that v1 API has

Fixes bug 1038552

Change-Id: Ieab82937822ad907493d4b538fd75e571416bf16
This commit is contained in:
isethi 2012-08-22 16:44:13 +00:00
parent 4c038b0d85
commit 80c099e0b4
5 changed files with 103 additions and 18 deletions

View File

@ -27,12 +27,14 @@ import glance.store
class ImageDataController(object):
def __init__(self, db_api=None, store_api=None, policy_enforcer=None):
def __init__(self, db_api=None, store_api=None,
policy_enforcer=None, notifier=None):
self.db_api = db_api or glance.db.get_api()
self.db_api.configure_db()
self.store_api = store_api or glance.store
self.store_api.create_stores()
self.policy = policy_enforcer or policy.Enforcer()
self.notifier = notifier or glance.notifier.Notifier()
def _get_image(self, context, image_id):
try:
@ -55,11 +57,12 @@ class ImageDataController(object):
req.context, 'file', image_id, data, size)
except exception.Duplicate:
raise webob.exc.HTTPConflict()
v2.update_image_read_acl(req, self.db_api, image)
values = {'location': location, 'size': size, 'checksum': checksum}
self.db_api.image_update(req.context, image_id, values)
else:
v2.update_image_read_acl(req, self.db_api, image)
values = {'location': location, 'size': size, 'checksum': checksum}
self.db_api.image_update(req.context, image_id, values)
updated_image = self._get_image(req.context, image_id)
self.notifier.info('image.upload', updated_image)
def download(self, req, image_id):
self._enforce(req, 'download_image')
@ -92,6 +95,10 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
class ResponseSerializer(wsgi.JSONResponseSerializer):
def __init__(self, notifier=None):
super(ResponseSerializer, self).__init__()
self.notifier = notifier or glance.notifier.Notifier()
def download(self, response, result):
size = result['meta']['size']
checksum = result['meta']['checksum']
@ -99,9 +106,8 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
response.headers['Content-Type'] = 'application/octet-stream'
if checksum:
response.headers['Content-MD5'] = checksum
notifier = glance.notifier.Notifier()
response.app_iter = common.size_checked_iter(
response, result['meta'], size, result['data'], notifier)
response, result['meta'], size, result['data'], self.notifier)
def upload(self, response, result):
response.status_int = 201

View File

@ -26,6 +26,7 @@ from glance.common import exception
from glance.common import utils
from glance.common import wsgi
import glance.db
import glance.notifier
from glance.openstack.common import cfg
import glance.openstack.common.log as logging
from glance.openstack.common import timeutils
@ -38,10 +39,11 @@ CONF = cfg.CONF
class ImagesController(object):
def __init__(self, db_api=None, policy_enforcer=None):
def __init__(self, db_api=None, policy_enforcer=None, notifier=None):
self.db_api = db_api or glance.db.get_api()
self.db_api.configure_db()
self.policy = policy_enforcer or policy.Enforcer()
self.notifier = notifier or glance.notifier.Notifier()
def _enforce(self, req, action):
"""Authorize an action against our policies"""
@ -95,8 +97,9 @@ class ImagesController(object):
image['tags'] = []
v2.update_image_read_acl(req, self.db_api, image)
return self._normalize_properties(dict(image))
image = self._normalize_properties(dict(image))
self.notifier.info('image.update', image)
return image
def index(self, req, marker=None, limit=None, sort_key='created_at',
sort_dir='desc', filters={}):
@ -151,7 +154,9 @@ class ImagesController(object):
try:
image = self.db_api.image_update(req.context, image_id, image)
except (exception.NotFound, exception.Forbidden):
raise webob.exc.HTTPNotFound()
msg = ("Failed to find image %(image_id)s to update" % locals())
LOG.info(msg)
raise webob.exc.HTTPNotFound(explanation=msg)
image = self._normalize_properties(dict(image))
@ -163,6 +168,7 @@ class ImagesController(object):
else:
self._append_tags(req.context, image)
self.notifier.info('image.update', image)
return image
@utils.mutating
@ -171,13 +177,18 @@ class ImagesController(object):
image = self._get_image(req.context, image_id)
if image['protected']:
msg = _("Unable to delete as image is protected.")
msg = _("Unable to delete as image %(image_id)s is protected"
% locals())
raise webob.exc.HTTPForbidden(explanation=msg)
try:
self.db_api.image_destroy(req.context, image_id)
except (exception.NotFound, exception.Forbidden):
msg = ("Failed to find image %(image_id)s to delete" % locals())
LOG.info(msg)
raise webob.exc.HTTPNotFound()
else:
self.notifier.info('image.delete', image)
class RequestDeserializer(wsgi.JSONRequestDeserializer):

View File

@ -121,3 +121,28 @@ class FakePolicyEnforcer(object):
def set_rules(self, rules):
self.rules = rules
class FakeNotifier(object):
def __init__(self, *_args, **kwargs):
self.log = {'notification_type': "",
'event_type': "",
'payload': "", }
def warn(self, event_type, payload):
self.log['notification_type'] = "WARN"
self.log['event_type'] = event_type
self.log['payload'] = payload
def info(self, event_type, payload):
self.log['notification_type'] = "INFO"
self.log['event_type'] = event_type
self.log['payload'] = payload
def error(self, event_type, payload):
self.log['notification_type'] = "ERROR"
self.log['event_type'] = event_type
self.log['payload'] = payload
def get_log(self):
return self.log

View File

@ -29,11 +29,12 @@ class TestImagesController(base.StoreClearingUnitTest):
super(TestImagesController, self).setUp()
self.config(verbose=True, debug=True)
self.notifier = unit_test_utils.FakeNotifier()
self.controller = glance.api.v2.image_data.ImageDataController(
db_api=unit_test_utils.FakeDB(),
store_api=unit_test_utils.FakeStoreAPI(),
policy_enforcer=unit_test_utils.FakePolicyEnforcer())
policy_enforcer=unit_test_utils.FakePolicyEnforcer(),
notifier=self.notifier)
def test_download(self):
request = unit_test_utils.get_fake_request()
@ -59,6 +60,12 @@ class TestImagesController(base.StoreClearingUnitTest):
self.assertEqual(set(['data', 'meta']), set(output.keys()))
self.assertEqual(4, output['meta']['size'])
self.assertEqual('YYYY', output['data'])
output_log = self.notifier.get_log()
expected_log = {'notification_type': "INFO",
'event_type': "image.upload",
'payload': output['meta'],
}
self.assertEqual(output_log, expected_log)
def test_upload_non_existent_image(self):
request = unit_test_utils.get_fake_request()
@ -165,7 +172,8 @@ class TestImageDataSerializer(test_utils.BaseTestCase):
def setUp(self):
super(TestImageDataSerializer, self).setUp()
self.serializer = glance.api.v2.image_data.ResponseSerializer()
self.serializer = glance.api.v2.image_data.ResponseSerializer(
notifier=unit_test_utils.FakeNotifier())
def test_download(self):
request = webob.Request.blank('/')

View File

@ -75,9 +75,11 @@ class TestImagesController(test_utils.BaseTestCase):
super(TestImagesController, self).setUp()
self.db = unit_test_utils.FakeDB()
self.policy = unit_test_utils.FakePolicyEnforcer()
self.notifier = unit_test_utils.FakeNotifier()
self._create_images()
self.controller = glance.api.v2.images.ImagesController(self.db,
self.policy)
self.policy,
self.notifier)
glance.store.create_stores()
def _create_images(self):
@ -308,18 +310,36 @@ class TestImagesController(test_utils.BaseTestCase):
self.assertEqual({}, output['properties'])
self.assertEqual([], output['tags'])
self.assertEqual(False, output['is_public'])
output_log = self.notifier.get_log()
expected_log = {'notification_type': "INFO",
'event_type': "image.update",
'payload': output,
}
self.assertEqual(output_log, expected_log)
def test_create_public_image_as_admin(self):
request = unit_test_utils.get_fake_request()
image = {'name': 'image-1', 'is_public': True}
output = self.controller.create(request, image)
self.assertEqual(True, output['is_public'])
output_log = self.notifier.get_log()
expected_log = {'notification_type': "INFO",
'event_type': "image.update",
'payload': output,
}
self.assertEqual(output_log, expected_log)
def test_create_duplicate_tags(self):
request = unit_test_utils.get_fake_request()
image = {'tags': ['ping', 'ping']}
output = self.controller.create(request, image)
self.assertEqual(['ping'], output['tags'])
output_log = self.notifier.get_log()
expected_log = {'notification_type': "INFO",
'event_type': "image.update",
'payload': output,
}
self.assertEqual(output_log, expected_log)
def test_update(self):
request = unit_test_utils.get_fake_request()
@ -328,6 +348,12 @@ class TestImagesController(test_utils.BaseTestCase):
self.assertEqual(UUID1, output['id'])
self.assertEqual('image-2', output['name'])
self.assertNotEqual(output['created_at'], output['updated_at'])
output_log = self.notifier.get_log()
expected_log = {'notification_type': "INFO",
'event_type': "image.update",
'payload': output,
}
self.assertEqual(output_log, expected_log)
def test_update_non_existent(self):
request = unit_test_utils.get_fake_request()
@ -340,11 +366,20 @@ class TestImagesController(test_utils.BaseTestCase):
image = {'tags': ['ping', 'ping']}
output = self.controller.update(request, UUID1, image)
self.assertEqual(['ping'], output['tags'])
output_log = self.notifier.get_log()
expected_log = {'notification_type': "INFO",
'event_type': "image.update",
'payload': output,
}
self.assertEqual(output_log, expected_log)
def test_delete(self):
request = unit_test_utils.get_fake_request()
try:
self.controller.delete(request, UUID1)
image = self.controller.delete(request, UUID1)
output_log = self.notifier.get_log()
self.assertEqual(output_log['notification_type'], "INFO")
self.assertEqual(output_log['event_type'], "image.delete")
except Exception as e:
self.fail("Delete raised exception: %s" % e)