diff options
| author | Brian Waldon <brian.waldon@rackspace.com> | 2011-06-30 13:18:11 +0000 |
|---|---|---|
| committer | Tarmac <> | 2011-06-30 13:18:11 +0000 |
| commit | edfacac605f6887d1b093c8c79a143d28e2083d9 (patch) | |
| tree | 3c093a36550c9105e7cc5710b59bbb8150acfe72 | |
| parent | d77526e357fe3764107d4d5fda768b69b52fb015 (diff) | |
| parent | 26d8486a168c1a9b88bd0025cf0106e0b0ce3be4 (diff) | |
- add metadata container to /images/detail and /images/<id> responses
- update xml serialization to encode image entities properly
| -rw-r--r-- | nova/api/openstack/image_metadata.py | 18 | ||||
| -rw-r--r-- | nova/api/openstack/images.py | 72 | ||||
| -rw-r--r-- | nova/api/openstack/views/images.py | 3 | ||||
| -rw-r--r-- | nova/tests/api/openstack/test_image_metadata.py | 222 | ||||
| -rw-r--r-- | nova/tests/api/openstack/test_images.py | 483 |
5 files changed, 623 insertions, 175 deletions
diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py index c0e92f2fc..638b1ec15 100644 --- a/nova/api/openstack/image_metadata.py +++ b/nova/api/openstack/image_metadata.py @@ -112,18 +112,18 @@ class Controller(object): class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer): - def __init__(self): - xmlns = wsgi.XMLNS_V11 + def __init__(self, xmlns=wsgi.XMLNS_V11): super(ImageMetadataXMLSerializer, self).__init__(xmlns=xmlns) def _meta_item_to_xml(self, doc, key, value): node = doc.createElement('meta') - node.setAttribute('key', key) - text = doc.createTextNode(value) + doc.appendChild(node) + node.setAttribute('key', '%s' % key) + text = doc.createTextNode('%s' % value) node.appendChild(text) return node - def _meta_list_to_xml(self, xml_doc, meta_items): + def meta_list_to_xml(self, xml_doc, meta_items): container_node = xml_doc.createElement('metadata') for (key, value) in meta_items: item_node = self._meta_item_to_xml(xml_doc, key, value) @@ -133,9 +133,10 @@ class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer): def _meta_list_to_xml_string(self, metadata_dict): xml_doc = minidom.Document() items = metadata_dict['metadata'].items() - container_node = self._meta_list_to_xml(xml_doc, items) + container_node = self.meta_list_to_xml(xml_doc, items) + xml_doc.appendChild(container_node) self._add_xmlns(container_node) - return container_node.toprettyxml(indent=' ') + return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') def index(self, metadata_dict): return self._meta_list_to_xml_string(metadata_dict) @@ -147,8 +148,9 @@ class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer): xml_doc = minidom.Document() item_key, item_value = meta_item_dict.items()[0] item_node = self._meta_item_to_xml(xml_doc, item_key, item_value) + xml_doc.appendChild(item_node) self._add_xmlns(item_node) - return item_node.toprettyxml(indent=' ') + return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') def show(self, meta_item_dict): return self._meta_item_to_xml_string(meta_item_dict['meta']) diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 0ab764199..bde9507c8 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -16,6 +16,7 @@ import os.path import webob.exc +from xml.dom import minidom from nova import compute from nova import exception @@ -25,6 +26,7 @@ from nova import log from nova import utils from nova.api.openstack import common from nova.api.openstack import faults +from nova.api.openstack import image_metadata from nova.api.openstack.views import images as images_view from nova.api.openstack import wsgi @@ -260,17 +262,69 @@ class ControllerV11(Controller): return {'instance_ref': server_ref} +class ImageXMLSerializer(wsgi.XMLDictSerializer): + + metadata = { + "attributes": { + "image": ["id", "name", "updated", "created", "status", + "serverId", "progress", "serverRef"], + "link": ["rel", "type", "href"], + }, + } + + xmlns = wsgi.XMLNS_V11 + + def __init__(self): + self.metadata_serializer = image_metadata.ImageMetadataXMLSerializer() + + def _image_to_xml(self, xml_doc, image): + try: + metadata = image.pop('metadata').items() + except Exception: + LOG.debug(_("Image object missing metadata attribute")) + metadata = {} + + node = self._to_xml_node(xml_doc, self.metadata, 'image', image) + metadata_node = self.metadata_serializer.meta_list_to_xml(xml_doc, + metadata) + node.appendChild(metadata_node) + return node + + def _image_list_to_xml(self, xml_doc, images): + container_node = xml_doc.createElement('images') + for image in images: + item_node = self._image_to_xml(xml_doc, image) + container_node.appendChild(item_node) + return container_node + + def _image_to_xml_string(self, image): + xml_doc = minidom.Document() + item_node = self._image_to_xml(xml_doc, image) + self._add_xmlns(item_node) + return item_node.toprettyxml(indent=' ') + + def _image_list_to_xml_string(self, images): + xml_doc = minidom.Document() + container_node = self._image_list_to_xml(xml_doc, images) + self._add_xmlns(container_node) + return container_node.toprettyxml(indent=' ') + + def detail(self, images_dict): + return self._image_list_to_xml_string(images_dict['images']) + + def show(self, image_dict): + return self._image_to_xml_string(image_dict['image']) + + def create(self, image_dict): + return self._image_to_xml_string(image_dict['image']) + + def create_resource(version='1.0'): controller = { '1.0': ControllerV10, '1.1': ControllerV11, }[version]() - xmlns = { - '1.0': wsgi.XMLNS_V10, - '1.1': wsgi.XMLNS_V11, - }[version] - metadata = { "attributes": { "image": ["id", "name", "updated", "created", "status", @@ -279,9 +333,13 @@ def create_resource(version='1.0'): }, } + xml_serializer = { + '1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10), + '1.1': ImageXMLSerializer(), + }[version] + serializers = { - 'application/xml': wsgi.XMLDictSerializer(xmlns=xmlns, - metadata=metadata), + 'application/xml': xml_serializer, } return wsgi.Resource(controller, serializers=serializers) diff --git a/nova/api/openstack/views/images.py b/nova/api/openstack/views/images.py index d6a054102..8d2303bcd 100644 --- a/nova/api/openstack/views/images.py +++ b/nova/api/openstack/views/images.py @@ -105,6 +105,9 @@ class ViewBuilderV11(ViewBuilder): image = ViewBuilder.build(self, image_obj, detail) href = self.generate_href(image_obj["id"]) + if detail: + image["metadata"] = image_obj.get("properties", {}) + image["links"] = [{ "rel": "self", "href": href, diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py index 730af3665..d9fb61e2a 100644 --- a/nova/tests/api/openstack/test_image_metadata.py +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -24,6 +24,7 @@ import xml.dom.minidom as minidom from nova import flags from nova.api import openstack +from nova import test from nova.tests.api.openstack import fakes import nova.wsgi @@ -31,7 +32,7 @@ import nova.wsgi FLAGS = flags.FLAGS -class ImageMetaDataTest(unittest.TestCase): +class ImageMetaDataTest(test.TestCase): IMAGE_FIXTURES = [ {'status': 'active', @@ -112,30 +113,6 @@ class ImageMetaDataTest(unittest.TestCase): for (key, value) in res_dict['metadata'].items(): self.assertEqual(value, res_dict['metadata'][key]) - def test_index_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'metadata': { - 'one': 'two', - 'three': 'four', - }, - } - output = serializer.index(fixture) - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> - <meta key="three"> - four - </meta> - <meta key="one"> - two - </meta> - </metadata> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - def test_show(self): req = webob.Request.blank('/v1.1/images/1/meta/key1') req.environ['api.version'] = '1.1' @@ -146,24 +123,6 @@ class ImageMetaDataTest(unittest.TestCase): self.assertEqual(len(res_dict['meta']), 1) self.assertEqual('value1', res_dict['meta']['key1']) - def test_show_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'meta': { - 'one': 'two', - }, - } - output = serializer.show(fixture) - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> - two - </meta> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - def test_show_not_found(self): req = webob.Request.blank('/v1.1/images/1/meta/key9') req.environ['api.version'] = '1.1' @@ -185,34 +144,6 @@ class ImageMetaDataTest(unittest.TestCase): self.assertEqual('value2', res_dict['metadata']['key2']) self.assertEqual(1, len(res_dict)) - def test_create_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'metadata': { - 'key9': 'value9', - 'key2': 'value2', - 'key1': 'value1', - }, - } - output = serializer.create(fixture) - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> - <meta key="key2"> - value2 - </meta> - <meta key="key9"> - value9 - </meta> - <meta key="key1"> - value1 - </meta> - </metadata> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - def test_update_item(self): req = webob.Request.blank('/v1.1/images/1/meta/key1') req.environ['api.version'] = '1.1' @@ -235,24 +166,6 @@ class ImageMetaDataTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) - def test_update_item_xml(self): - serializer = openstack.image_metadata.ImageMetadataXMLSerializer() - fixture = { - 'meta': { - 'one': 'two', - }, - } - output = serializer.update(fixture) - actual = minidom.parseString(output.replace(" ", "")) - - expected = minidom.parseString(""" - <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> - two - </meta> - """.replace(" ", "")) - - self.assertEqual(expected.toxml(), actual.toxml()) - def test_update_item_too_many_keys(self): req = webob.Request.blank('/v1.1/images/1/meta/key1') req.environ['api.version'] = '1.1' @@ -306,3 +219,134 @@ class ImageMetaDataTest(unittest.TestCase): req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) + + +class ImageMetadataXMLSerializationTest(test.TestCase): + + def test_index_xml(self): + serializer = openstack.image_metadata.ImageMetadataXMLSerializer() + fixture = { + 'metadata': { + 'one': 'two', + 'three': 'four', + }, + } + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="three"> + four + </meta> + <meta key="one"> + two + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index_xml_null(self): + serializer = openstack.image_metadata.ImageMetadataXMLSerializer() + fixture = { + 'metadata': { + None: None, + }, + } + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="None"> + None + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index_xml_unicode(self): + serializer = openstack.image_metadata.ImageMetadataXMLSerializer() + fixture = { + 'metadata': { + u'three': u'Jos\xe9', + }, + } + output = serializer.serialize(fixture, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(u""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="three"> + Jos\xe9 + </meta> + </metadata> + """.encode("UTF-8").replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_show_xml(self): + serializer = openstack.image_metadata.ImageMetadataXMLSerializer() + fixture = { + 'meta': { + 'one': 'two', + }, + } + output = serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> + two + </meta> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_update_item_xml(self): + serializer = openstack.image_metadata.ImageMetadataXMLSerializer() + fixture = { + 'meta': { + 'one': 'two', + }, + } + output = serializer.serialize(fixture, 'update') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one"> + two + </meta> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_create_xml(self): + serializer = openstack.image_metadata.ImageMetadataXMLSerializer() + fixture = { + 'metadata': { + 'key9': 'value9', + 'key2': 'value2', + 'key1': 'value1', + }, + } + output = serializer.serialize(fixture, 'create') + actual = minidom.parseString(output.replace(" ", "")) + + expected = minidom.parseString(""" + <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"> + <meta key="key2"> + value2 + </meta> + <meta key="key9"> + value9 + </meta> + <meta key="key1"> + value1 + </meta> + </metadata> + """.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index e11e1c046..1e046531c 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -394,20 +394,25 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertEqual(expected_image, actual_image) def test_get_image_v1_1(self): - request = webob.Request.blank('/v1.1/images/123') + request = webob.Request.blank('/v1.1/images/124') response = request.get_response(fakes.wsgi_app()) actual_image = json.loads(response.body) - href = "http://localhost/v1.1/images/123" + href = "http://localhost/v1.1/images/124" expected_image = { "image": { - "id": 123, - "name": "public image", + "id": 124, + "name": "queued snapshot", + "serverRef": "http://localhost/v1.1/servers/42", "updated": self.NOW_API_FORMAT, "created": self.NOW_API_FORMAT, - "status": "ACTIVE", + "status": "QUEUED", + "metadata": { + "instance_ref": "http://localhost/v1.1/servers/42", + "user_id": "1", + }, "links": [{ "rel": "self", "href": href, @@ -465,34 +470,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertEqual(expected_image.toxml(), actual_image.toxml()) - def test_get_image_v1_1_xml(self): - request = webob.Request.blank('/v1.1/images/123') - request.accept = "application/xml" - response = request.get_response(fakes.wsgi_app()) - - actual_image = minidom.parseString(response.body.replace(" ", "")) - - expected_href = "http://localhost/v1.1/images/123" - expected_now = self.NOW_API_FORMAT - expected_image = minidom.parseString(""" - <image id="123" - name="public image" - updated="%(expected_now)s" - created="%(expected_now)s" - status="ACTIVE" - xmlns="http://docs.openstack.org/compute/api/v1.1"> - <links> - <link href="%(expected_href)s" rel="self"/> - <link href="%(expected_href)s" rel="bookmark" - type="application/json" /> - <link href="%(expected_href)s" rel="bookmark" - type="application/xml" /> - </links> - </image> - """.replace(" ", "") % (locals())) - - self.assertEqual(expected_image.toxml(), actual_image.toxml()) - def test_get_image_404_json(self): request = webob.Request.blank('/v1.0/images/NonExistantImage') response = request.get_response(fakes.wsgi_app()) @@ -665,6 +642,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): expected = [{ 'id': 123, 'name': 'public image', + 'metadata': {}, 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'ACTIVE', @@ -686,7 +664,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): { 'id': 124, 'name': 'queued snapshot', - 'serverRef': "http://localhost:8774/v1.1/servers/42", + 'metadata': { + u'instance_ref': u'http://localhost/v1.1/servers/42', + u'user_id': u'1', + }, + 'serverRef': "http://localhost/v1.1/servers/42", 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'QUEUED', @@ -708,7 +690,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): { 'id': 125, 'name': 'saving snapshot', - 'serverRef': "http://localhost:8774/v1.1/servers/42", + 'metadata': { + u'instance_ref': u'http://localhost/v1.1/servers/42', + u'user_id': u'1', + }, + 'serverRef': "http://localhost/v1.1/servers/42", 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'SAVING', @@ -731,7 +717,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): { 'id': 126, 'name': 'active snapshot', - 'serverRef': "http://localhost:8774/v1.1/servers/42", + 'metadata': { + u'instance_ref': u'http://localhost/v1.1/servers/42', + u'user_id': u'1', + }, + 'serverRef': "http://localhost/v1.1/servers/42", 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'ACTIVE', @@ -753,7 +743,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): { 'id': 127, 'name': 'killed snapshot', - 'serverRef': "http://localhost:8774/v1.1/servers/42", + 'metadata': { + u'instance_ref': u'http://localhost/v1.1/servers/42', + u'user_id': u'1', + }, + 'serverRef': "http://localhost/v1.1/servers/42", 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'FAILED', @@ -775,6 +769,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): { 'id': 129, 'name': None, + 'metadata': {}, 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'ACTIVE', @@ -1108,39 +1103,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): response = req.get_response(fakes.wsgi_app()) self.assertEqual(400, response.status_int) - def test_create_image_v1_1_xml_serialization(self): - - body = dict(image=dict(serverRef='123', name='Snapshot 1')) - req = webob.Request.blank('/v1.1/images') - req.method = 'POST' - req.body = json.dumps(body) - req.headers["content-type"] = "application/json" - req.headers["accept"] = "application/xml" - response = req.get_response(fakes.wsgi_app()) - self.assertEqual(200, response.status_int) - resp_xml = minidom.parseString(response.body.replace(" ", "")) - expected_href = "http://localhost/v1.1/images/123" - expected_image = minidom.parseString(""" - <image - created="None" - id="123" - name="Snapshot 1" - serverRef="http://localhost/v1.1/servers/123" - status="ACTIVE" - updated="None" - xmlns="http://docs.openstack.org/compute/api/v1.1"> - <links> - <link href="%(expected_href)s" rel="self"/> - <link href="%(expected_href)s" rel="bookmark" - type="application/json" /> - <link href="%(expected_href)s" rel="bookmark" - type="application/xml" /> - </links> - </image> - """.replace(" ", "") % (locals())) - - self.assertEqual(expected_image.toxml(), resp_xml.toxml()) - def test_create_image_v1_1_no_server_ref(self): body = dict(image=dict(name='Snapshot 1')) @@ -1171,7 +1133,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): image_id += 1 # Snapshot for User 1 - server_ref = 'http://localhost:8774/v1.1/servers/42' + server_ref = 'http://localhost/v1.1/servers/42' snapshot_properties = {'instance_ref': server_ref, 'user_id': '1'} for status in ('queued', 'saving', 'active', 'killed'): add_fixture(id=image_id, name='%s snapshot' % status, @@ -1193,3 +1155,382 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): image_id += 1 return fixtures + + +class ImageXMLSerializationTest(test.TestCase): + + TIMESTAMP = "2010-10-11T10:30:22Z" + SERVER_HREF = 'http://localhost/v1.1/servers/123' + IMAGE_HREF = 'http://localhost/v1.1/images/%s' + + def test_show(self): + serializer = images.ImageXMLSerializer() + + fixture = { + 'image': { + 'id': 1, + 'name': 'Image1', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'ACTIVE', + 'metadata': { + 'key1': 'value1', + }, + 'links': [ + { + 'href': self.IMAGE_HREF % (1,), + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + } + + output = serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected_server_href = self.SERVER_HREF + expected_href = self.IMAGE_HREF % (1, ) + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <image id="1" + name="Image1" + serverRef="%(expected_server_href)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="ACTIVE" + xmlns="http://docs.openstack.org/compute/api/v1.1"> + <links> + <link href="%(expected_href)s" rel="bookmark" + type="application/json" /> + </links> + <metadata> + <meta key="key1"> + value1 + </meta> + </metadata> + </image> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_show_zero_metadata(self): + serializer = images.ImageXMLSerializer() + + fixture = { + 'image': { + 'id': 1, + 'name': 'Image1', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'ACTIVE', + 'metadata': {}, + 'links': [ + { + 'href': self.IMAGE_HREF % (1,), + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + } + + output = serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected_server_href = self.SERVER_HREF + expected_href = self.IMAGE_HREF % (1, ) + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <image id="1" + name="Image1" + serverRef="%(expected_server_href)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="ACTIVE" + xmlns="http://docs.openstack.org/compute/api/v1.1"> + <links> + <link href="%(expected_href)s" rel="bookmark" + type="application/json" /> + </links> + <metadata /> + </image> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_show_image_no_metadata_key(self): + serializer = images.ImageXMLSerializer() + + fixture = { + 'image': { + 'id': 1, + 'name': 'Image1', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'ACTIVE', + 'links': [ + { + 'href': self.IMAGE_HREF % (1,), + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + + }, + } + + output = serializer.serialize(fixture, 'show') + actual = minidom.parseString(output.replace(" ", "")) + + expected_server_href = self.SERVER_HREF + expected_href = self.IMAGE_HREF % (1, ) + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <image id="1" + name="Image1" + serverRef="%(expected_server_href)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="ACTIVE" + xmlns="http://docs.openstack.org/compute/api/v1.1"> + <links> + <link href="%(expected_href)s" rel="bookmark" + type="application/json" /> + </links> + <metadata /> + </image> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index(self): + serializer = images.ImageXMLSerializer() + + fixtures = { + 'images': [ + { + 'id': 1, + 'name': 'Image1', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'ACTIVE', + 'links': [ + { + 'href': 'http://localhost/v1.1/images/1', + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + { + 'id': 2, + 'name': 'queued image', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'QUEUED', + 'links': [ + { + 'href': 'http://localhost/v1.1/images/2', + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + ], + } + + output = serializer.serialize(fixtures, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected_serverRef = self.SERVER_HREF + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <images xmlns="http://docs.openstack.org/compute/api/v1.1"> + <image id="1" + name="Image1" + serverRef="%(expected_serverRef)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="ACTIVE"> + <links> + <link href="http://localhost/v1.1/images/1" rel="bookmark" + type="application/json" /> + </links> + </image> + <image id="2" + name="queued image" + serverRef="%(expected_serverRef)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="QUEUED"> + <links> + <link href="http://localhost/v1.1/images/2" rel="bookmark" + type="application/json" /> + </links> + </image> + </images> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_index_zero_images(self): + serializer = images.ImageXMLSerializer() + + fixtures = { + 'images': [], + } + + output = serializer.serialize(fixtures, 'index') + actual = minidom.parseString(output.replace(" ", "")) + + expected_serverRef = self.SERVER_HREF + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <images xmlns="http://docs.openstack.org/compute/api/v1.1" /> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_detail(self): + serializer = images.ImageXMLSerializer() + + fixtures = { + 'images': [ + { + 'id': 1, + 'name': 'Image1', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'ACTIVE', + 'metadata': { + 'key1': 'value1', + 'key2': 'value2', + }, + 'links': [ + { + 'href': 'http://localhost/v1.1/images/1', + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + { + 'id': 2, + 'name': 'queued image', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'metadata': {}, + 'status': 'QUEUED', + 'links': [ + { + 'href': 'http://localhost/v1.1/images/2', + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + ], + } + + output = serializer.serialize(fixtures, 'detail') + actual = minidom.parseString(output.replace(" ", "")) + + expected_serverRef = self.SERVER_HREF + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <images xmlns="http://docs.openstack.org/compute/api/v1.1"> + <image id="1" + name="Image1" + serverRef="%(expected_serverRef)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="ACTIVE"> + <links> + <link href="http://localhost/v1.1/images/1" rel="bookmark" + type="application/json" /> + </links> + <metadata> + <meta key="key2"> + value2 + </meta> + <meta key="key1"> + value1 + </meta> + </metadata> + </image> + <image id="2" + name="queued image" + serverRef="%(expected_serverRef)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="QUEUED"> + <links> + <link href="http://localhost/v1.1/images/2" rel="bookmark" + type="application/json" /> + </links> + <metadata /> + </image> + </images> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_create(self): + serializer = images.ImageXMLSerializer() + + fixture = { + 'image': { + 'id': 1, + 'name': 'Image1', + 'created': self.TIMESTAMP, + 'updated': self.TIMESTAMP, + 'serverRef': self.SERVER_HREF, + 'status': 'ACTIVE', + 'metadata': { + 'key1': 'value1', + }, + 'links': [ + { + 'href': self.IMAGE_HREF % (1,), + 'rel': 'bookmark', + 'type': 'application/json', + }, + ], + }, + } + + output = serializer.serialize(fixture, 'create') + actual = minidom.parseString(output.replace(" ", "")) + + expected_server_href = self.SERVER_HREF + expected_href = self.IMAGE_HREF % (1, ) + expected_now = self.TIMESTAMP + expected = minidom.parseString(""" + <image id="1" + name="Image1" + serverRef="%(expected_server_href)s" + updated="%(expected_now)s" + created="%(expected_now)s" + status="ACTIVE" + xmlns="http://docs.openstack.org/compute/api/v1.1"> + <links> + <link href="%(expected_href)s" rel="bookmark" + type="application/json" /> + </links> + <metadata> + <meta key="key1"> + value1 + </meta> + </metadata> + </image> + """.replace(" ", "") % (locals())) + + self.assertEqual(expected.toxml(), actual.toxml()) |
