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:
parent
4c038b0d85
commit
80c099e0b4
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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('/')
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user