Skip to content
Permalink
Browse files

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
  • Loading branch information
isethi
isethi committed Aug 22, 2012
1 parent 4c038b0 commit 80c099e0b41b3f2f9684b06f1f4eee8e2776969e
@@ -27,12 +27,14 @@


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 @@ def upload(self, req, image_id, data, size):
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,16 +95,19 @@ def upload(self, request):


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']
response.headers['Content-Length'] = size
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 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 @@


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 @@ def create(self, req, image):
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 @@ def update(self, req, image_id, image):
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 @@ def update(self, req, image_id, image):
else:
self._append_tags(req.context, image)

self.notifier.info('image.update', image)
return image

@utils.mutating
@@ -171,13 +177,18 @@ def delete(self, req, image_id):
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 @@ def enforce(self, _ctxt, action, target=None, **kwargs):

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 @@ def setUp(self):
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 @@ def test_upload_download(self):
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 @@ def setUp(self):
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 @@ def test_create(self):
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 @@ def test_update(self):
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 @@ def test_update_duplicate_tags(self):
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)

0 comments on commit 80c099e

Please sign in to comment.
You can’t perform that action at this time.