summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Waldon <brian.waldon@rackspace.com>2011-07-25 23:43:22 +0000
committerTarmac <>2011-07-25 23:43:22 +0000
commit83033f69e19832dc50fccf5b833189f0c4e8de63 (patch)
treedfa52c79ddfa08ee66560ffbeb45c7884b491989
parent650e1e78ed01e93ae1f89ee0f3eb81d6223caf03 (diff)
parent175e42fe2310a3aff69527d5623d92f3d0b19258 (diff)
downloadnova-83033f69e19832dc50fccf5b833189f0c4e8de63.tar.gz
nova-83033f69e19832dc50fccf5b833189f0c4e8de63.tar.xz
nova-83033f69e19832dc50fccf5b833189f0c4e8de63.zip
- Updates /images/<id>/meta and /images/<id>/meta/<key> to respect the latest specification
- Renames ../meta to ../metadata - Adds PUT on ../metadata to set entire container (controller action is called update_all)
-rw-r--r--nova/api/openstack/__init__.py10
-rw-r--r--nova/api/openstack/create_instance_helper.py45
-rw-r--r--nova/api/openstack/image_metadata.py53
-rw-r--r--nova/api/openstack/wsgi.py42
-rw-r--r--nova/tests/api/openstack/test_image_metadata.py184
-rw-r--r--nova/tests/api/openstack/test_wsgi.py7
6 files changed, 253 insertions, 88 deletions
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
index e87d7c754..868b98a31 100644
--- a/nova/api/openstack/__init__.py
+++ b/nova/api/openstack/__init__.py
@@ -164,11 +164,17 @@ class APIRouterV11(APIRouter):
def _setup_routes(self, mapper):
super(APIRouterV11, self)._setup_routes(mapper, '1.1')
- mapper.resource("image_meta", "meta",
- controller=image_metadata.create_resource(),
+ image_metadata_controller = image_metadata.create_resource()
+ mapper.resource("image_meta", "metadata",
+ controller=image_metadata_controller,
parent_resource=dict(member_name='image',
collection_name='images'))
+ mapper.connect("metadata", "/images/{image_id}/metadata",
+ controller=image_metadata_controller,
+ action='update_all',
+ conditions={"method": ['PUT']})
+
mapper.resource("server_meta", "meta",
controller=server_metadata.create_resource(),
parent_resource=dict(member_name='server',
diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py
index 55c07ed81..f8317565e 100644
--- a/nova/api/openstack/create_instance_helper.py
+++ b/nova/api/openstack/create_instance_helper.py
@@ -285,7 +285,7 @@ class CreateInstanceHelper(object):
return password
-class ServerXMLDeserializer(wsgi.XMLDeserializer):
+class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer):
"""
Deserializer to handle xml-formatted server create requests.
@@ -302,11 +302,12 @@ class ServerXMLDeserializer(wsgi.XMLDeserializer):
def _extract_server(self, node):
"""Marshal the server attribute of a parsed request"""
server = {}
- server_node = self._find_first_child_named(node, 'server')
+ server_node = self.find_first_child_named(node, 'server')
for attr in ["name", "imageId", "flavorId", "imageRef", "flavorRef"]:
if server_node.getAttribute(attr):
server[attr] = server_node.getAttribute(attr)
- metadata = self._extract_metadata(server_node)
+ metadata_node = self.find_first_child_named(server_node, "metadata")
+ metadata = self.extract_metadata(metadata_node)
if metadata is not None:
server["metadata"] = metadata
personality = self._extract_personality(server_node)
@@ -314,49 +315,17 @@ class ServerXMLDeserializer(wsgi.XMLDeserializer):
server["personality"] = personality
return server
- def _extract_metadata(self, server_node):
- """Marshal the metadata attribute of a parsed request"""
- metadata_node = self._find_first_child_named(server_node, "metadata")
- if metadata_node is None:
- return None
- metadata = {}
- for meta_node in self._find_children_named(metadata_node, "meta"):
- key = meta_node.getAttribute("key")
- metadata[key] = self._extract_text(meta_node)
- return metadata
-
def _extract_personality(self, server_node):
"""Marshal the personality attribute of a parsed request"""
personality_node = \
- self._find_first_child_named(server_node, "personality")
+ self.find_first_child_named(server_node, "personality")
if personality_node is None:
return None
personality = []
- for file_node in self._find_children_named(personality_node, "file"):
+ for file_node in self.find_children_named(personality_node, "file"):
item = {}
if file_node.hasAttribute("path"):
item["path"] = file_node.getAttribute("path")
- item["contents"] = self._extract_text(file_node)
+ item["contents"] = self.extract_text(file_node)
personality.append(item)
return personality
-
- def _find_first_child_named(self, parent, name):
- """Search a nodes children for the first child with a given name"""
- for node in parent.childNodes:
- if node.nodeName == name:
- return node
- return None
-
- def _find_children_named(self, parent, name):
- """Return all of a nodes children who have the given name"""
- for node in parent.childNodes:
- if node.nodeName == name:
- yield node
-
- def _extract_text(self, node):
- """Get the text field contained by the given node"""
- if len(node.childNodes) == 1:
- child = node.childNodes[0]
- if child.nodeType == child.TEXT_NODE:
- return child.nodeValue
- return ""
diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py
index c0fc8c09b..ee181c924 100644
--- a/nova/api/openstack/image_metadata.py
+++ b/nova/api/openstack/image_metadata.py
@@ -96,8 +96,16 @@ class Controller(object):
self._check_quota_limit(context, metadata)
img['properties'] = metadata
self.image_service.update(context, image_id, img, None)
+ return dict(meta=meta)
- return req.body
+ def update_all(self, req, image_id, body):
+ context = req.environ['nova.context']
+ img = self.image_service.show(context, image_id)
+ metadata = body.get('metadata', {})
+ self._check_quota_limit(context, metadata)
+ img['properties'] = metadata
+ self.image_service.update(context, image_id, img, None)
+ return dict(metadata=metadata)
def delete(self, req, image_id, id):
context = req.environ['nova.context']
@@ -110,6 +118,32 @@ class Controller(object):
self.image_service.update(context, image_id, img, None)
+class ImageMetadataXMLDeserializer(wsgi.MetadataXMLDeserializer):
+
+ def _extract_metadata_container(self, datastring):
+ dom = minidom.parseString(datastring)
+ metadata_node = self.find_first_child_named(dom, "metadata")
+ metadata = self.extract_metadata(metadata_node)
+ return {'body': {'metadata': metadata}}
+
+ def create(self, datastring):
+ return self._extract_metadata_container(datastring)
+
+ def update_all(self, datastring):
+ return self._extract_metadata_container(datastring)
+
+ def update(self, datastring):
+ dom = minidom.parseString(datastring)
+ metadata_item = self.extract_metadata(dom)
+ return {'body': {'meta': metadata_item}}
+
+
+class HeadersSerializer(wsgi.ResponseHeadersSerializer):
+
+ def delete(self, response, data):
+ response.status_int = 204
+
+
class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer):
def __init__(self, xmlns=wsgi.XMLNS_V11):
super(ImageMetadataXMLSerializer, self).__init__(xmlns=xmlns)
@@ -143,6 +177,9 @@ class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer):
def create(self, metadata_dict):
return self._meta_list_to_xml_string(metadata_dict)
+ def update_all(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
def _meta_item_to_xml_string(self, meta_item_dict):
xml_doc = minidom.Document()
item_key, item_value = meta_item_dict.items()[0]
@@ -157,11 +194,21 @@ class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer):
def update(self, meta_item_dict):
return self._meta_item_to_xml_string(meta_item_dict['meta'])
+ def default(self, *args, **kwargs):
+ return ''
+
def create_resource():
+ headers_serializer = HeadersSerializer()
+
+ body_deserializers = {
+ 'application/xml': ImageMetadataXMLDeserializer(),
+ }
+
body_serializers = {
'application/xml': ImageMetadataXMLSerializer(),
}
- serializer = wsgi.ResponseSerializer(body_serializers)
+ serializer = wsgi.ResponseSerializer(body_serializers, headers_serializer)
+ deserializer = wsgi.RequestDeserializer(body_deserializers)
- return wsgi.Resource(Controller(), serializer=serializer)
+ return wsgi.Resource(Controller(), deserializer, serializer)
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index c10cb3bc9..a28443d12 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -136,10 +136,44 @@ class XMLDeserializer(TextDeserializer):
listnames)
return result
+ def find_first_child_named(self, parent, name):
+ """Search a nodes children for the first child with a given name"""
+ for node in parent.childNodes:
+ if node.nodeName == name:
+ return node
+ return None
+
+ def find_children_named(self, parent, name):
+ """Return all of a nodes children who have the given name"""
+ for node in parent.childNodes:
+ if node.nodeName == name:
+ yield node
+
+ def extract_text(self, node):
+ """Get the text field contained by the given node"""
+ if len(node.childNodes) == 1:
+ child = node.childNodes[0]
+ if child.nodeType == child.TEXT_NODE:
+ return child.nodeValue
+ return ""
+
def default(self, datastring):
return {'body': self._from_xml(datastring)}
+class MetadataXMLDeserializer(XMLDeserializer):
+
+ def extract_metadata(self, metadata_node):
+ """Marshal the metadata attribute of a parsed request"""
+ if metadata_node is None:
+ return None
+ metadata = {}
+ for meta_node in self.find_children_named(metadata_node, "meta"):
+ key = meta_node.getAttribute("key")
+ metadata[key] = self.extract_text(meta_node)
+ return metadata
+
+
class RequestHeadersDeserializer(ActionDispatcher):
"""Default request headers deserializer"""
@@ -397,8 +431,9 @@ class ResponseSerializer(object):
def serialize_body(self, response, data, content_type, action):
response.headers['Content-Type'] = content_type
- serializer = self.get_body_serializer(content_type)
- response.body = serializer.serialize(data, action)
+ if data is not None:
+ serializer = self.get_body_serializer(content_type)
+ response.body = serializer.serialize(data, action)
def get_body_serializer(self, content_type):
try:
@@ -444,7 +479,7 @@ class Resource(wsgi.Application):
action, args, accept = self.deserializer.deserialize(request)
except exception.InvalidContentType:
msg = _("Unsupported Content-Type")
- return webob.exc.HTTPBadRequest(explanation=msg)
+ return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg))
except exception.MalformedRequestBody:
msg = _("Malformed request body")
return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg))
@@ -455,7 +490,6 @@ class Resource(wsgi.Application):
LOG.info(_("HTTP exception thrown: %s"), unicode(ex))
action_result = faults.Fault(ex)
- #TODO(bcwaldon): find a more elegant way to pass through non-dict types
if type(action_result) is dict or action_result is None:
response = self.serializer.serialize(action_result,
accept,
diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py
index d9fb61e2a..31ca18497 100644
--- a/nova/tests/api/openstack/test_image_metadata.py
+++ b/nova/tests/api/openstack/test_image_metadata.py
@@ -103,8 +103,7 @@ class ImageMetaDataTest(test.TestCase):
super(ImageMetaDataTest, self).tearDown()
def test_index(self):
- req = webob.Request.blank('/v1.1/images/1/meta')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(200, res.status_int)
@@ -114,8 +113,7 @@ class ImageMetaDataTest(test.TestCase):
self.assertEqual(value, res_dict['metadata'][key])
def test_show(self):
- req = webob.Request.blank('/v1.1/images/1/meta/key1')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata/key1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(200, res.status_int)
@@ -124,42 +122,66 @@ class ImageMetaDataTest(test.TestCase):
self.assertEqual('value1', res_dict['meta']['key1'])
def test_show_not_found(self):
- req = webob.Request.blank('/v1.1/images/1/meta/key9')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata/key9')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(404, res.status_int)
def test_create(self):
- req = webob.Request.blank('/v1.1/images/2/meta')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/2/metadata')
req.method = 'POST'
req.body = '{"metadata": {"key9": "value9"}}'
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
- res_dict = json.loads(res.body)
+
+ self.assertEqual(200, res.status_int)
+ actual_output = json.loads(res.body)
+
+ expected_output = {
+ 'metadata': {
+ 'key1': 'value1',
+ 'key2': 'value2',
+ 'key9': 'value9',
+ },
+ }
+
+ self.assertEqual(expected_output, actual_output)
+
+ def test_update_all(self):
+ req = webob.Request.blank('/v1.1/images/2/metadata')
+ req.method = 'PUT'
+ req.body = '{"metadata": {"key9": "value9"}}'
+ req.headers["content-type"] = "application/json"
+ res = req.get_response(fakes.wsgi_app())
+
self.assertEqual(200, res.status_int)
- self.assertEqual('value9', res_dict['metadata']['key9'])
- # other items should not be modified
- self.assertEqual('value1', res_dict['metadata']['key1'])
- self.assertEqual('value2', res_dict['metadata']['key2'])
- self.assertEqual(1, len(res_dict))
+ actual_output = json.loads(res.body)
+
+ expected_output = {
+ 'metadata': {
+ 'key9': 'value9',
+ },
+ }
+
+ self.assertEqual(expected_output, actual_output)
def test_update_item(self):
- req = webob.Request.blank('/v1.1/images/1/meta/key1')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata/key1')
req.method = 'PUT'
req.body = '{"meta": {"key1": "zz"}}'
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
+
self.assertEqual(200, res.status_int)
- res_dict = json.loads(res.body)
- self.assertTrue('meta' in res_dict)
- self.assertEqual(len(res_dict['meta']), 1)
- self.assertEqual('zz', res_dict['meta']['key1'])
+ actual_output = json.loads(res.body)
+ expected_output = {
+ 'meta': {
+ 'key1': 'zz',
+ },
+ }
+ self.assertEqual(actual_output, expected_output)
def test_update_item_bad_body(self):
- req = webob.Request.blank('/v1.1/images/1/meta/key1')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata/key1')
req.method = 'PUT'
req.body = '{"key1": "zz"}'
req.headers["content-type"] = "application/json"
@@ -167,8 +189,7 @@ class ImageMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_update_item_too_many_keys(self):
- req = webob.Request.blank('/v1.1/images/1/meta/key1')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata/key1')
req.method = 'PUT'
req.body = '{"meta": {"key1": "value1", "key2": "value2"}}'
req.headers["content-type"] = "application/json"
@@ -176,24 +197,38 @@ class ImageMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_update_item_body_uri_mismatch(self):
- req = webob.Request.blank('/v1.1/images/1/meta/bad')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/1/metadata/bad')
req.method = 'PUT'
req.body = '{"meta": {"key1": "value1"}}'
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(400, res.status_int)
+ def test_update_item_xml(self):
+ req = webob.Request.blank('/v1.1/images/1/metadata/key1')
+ req.method = 'PUT'
+ req.body = '<meta key="key1">five</meta>'
+ req.headers["content-type"] = "application/xml"
+ res = req.get_response(fakes.wsgi_app())
+
+ self.assertEqual(200, res.status_int)
+ actual_output = json.loads(res.body)
+ expected_output = {
+ 'meta': {
+ 'key1': 'five',
+ },
+ }
+ self.assertEqual(actual_output, expected_output)
+
def test_delete(self):
- req = webob.Request.blank('/v1.1/images/2/meta/key1')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/2/metadata/key1')
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
- self.assertEqual(200, res.status_int)
+ self.assertEqual(204, res.status_int)
+ self.assertEqual('', res.body)
def test_delete_not_found(self):
- req = webob.Request.blank('/v1.1/images/2/meta/blah')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/2/metadata/blah')
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(404, res.status_int)
@@ -203,8 +238,7 @@ class ImageMetaDataTest(test.TestCase):
for num in range(FLAGS.quota_metadata_items + 1):
data['metadata']['key%i' % num] = "blah"
json_string = str(data).replace("\'", "\"")
- req = webob.Request.blank('/v1.1/images/2/meta')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/2/metadata')
req.method = 'POST'
req.body = json_string
req.headers["content-type"] = "application/json"
@@ -212,8 +246,7 @@ class ImageMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
def test_too_many_metadata_items_on_put(self):
- req = webob.Request.blank('/v1.1/images/3/meta/blah')
- req.environ['api.version'] = '1.1'
+ req = webob.Request.blank('/v1.1/images/3/metadata/blah')
req.method = 'PUT'
req.body = '{"meta": {"blah": "blah"}}'
req.headers["content-type"] = "application/json"
@@ -221,9 +254,49 @@ class ImageMetaDataTest(test.TestCase):
self.assertEqual(400, res.status_int)
+class ImageMetadataXMLDeserializationTest(test.TestCase):
+
+ deserializer = openstack.image_metadata.ImageMetadataXMLDeserializer()
+
+ def test_create(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key='123'>asdf</meta>
+ <meta key='567'>jkl;</meta>
+ </metadata>"""
+ output = self.deserializer.deserialize(request_body, 'create')
+ expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
+ self.assertEquals(output, expected)
+
+ def test_create_empty(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"/>"""
+ output = self.deserializer.deserialize(request_body, 'create')
+ expected = {"body": {"metadata": {}}}
+ self.assertEquals(output, expected)
+
+ def test_update_all(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key='123'>asdf</meta>
+ <meta key='567'>jkl;</meta>
+ </metadata>"""
+ output = self.deserializer.deserialize(request_body, 'update_all')
+ expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
+ self.assertEquals(output, expected)
+
+ def test_update(self):
+ request_body = """
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1"
+ key='123'>asdf</meta>"""
+ output = self.deserializer.deserialize(request_body, 'update')
+ expected = {"body": {"meta": {"123": "asdf"}}}
+ self.assertEquals(output, expected)
+
+
class ImageMetadataXMLSerializationTest(test.TestCase):
- def test_index_xml(self):
+ def test_index(self):
serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
fixture = {
'metadata': {
@@ -247,7 +320,7 @@ class ImageMetadataXMLSerializationTest(test.TestCase):
self.assertEqual(expected.toxml(), actual.toxml())
- def test_index_xml_null(self):
+ def test_index_null(self):
serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
fixture = {
'metadata': {
@@ -267,7 +340,7 @@ class ImageMetadataXMLSerializationTest(test.TestCase):
self.assertEqual(expected.toxml(), actual.toxml())
- def test_index_xml_unicode(self):
+ def test_index_unicode(self):
serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
fixture = {
'metadata': {
@@ -287,7 +360,7 @@ class ImageMetadataXMLSerializationTest(test.TestCase):
self.assertEqual(expected.toxml(), actual.toxml())
- def test_show_xml(self):
+ def test_show(self):
serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
fixture = {
'meta': {
@@ -305,7 +378,31 @@ class ImageMetadataXMLSerializationTest(test.TestCase):
self.assertEqual(expected.toxml(), actual.toxml())
- def test_update_item_xml(self):
+ def test_update_all(self):
+ serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'key6': 'value6',
+ 'key4': 'value4',
+ },
+ }
+ output = serializer.serialize(fixture, 'update_all')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="key6">
+ value6
+ </meta>
+ <meta key="key4">
+ value4
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_update_item(self):
serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
fixture = {
'meta': {
@@ -323,7 +420,7 @@ class ImageMetadataXMLSerializationTest(test.TestCase):
self.assertEqual(expected.toxml(), actual.toxml())
- def test_create_xml(self):
+ def test_create(self):
serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
fixture = {
'metadata': {
@@ -350,3 +447,8 @@ class ImageMetadataXMLSerializationTest(test.TestCase):
""".replace(" ", ""))
self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_delete(self):
+ serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
+ output = serializer.serialize(None, 'delete')
+ self.assertEqual(output, '')
diff --git a/nova/tests/api/openstack/test_wsgi.py b/nova/tests/api/openstack/test_wsgi.py
index 5bdda7c7e..6dea78d17 100644
--- a/nova/tests/api/openstack/test_wsgi.py
+++ b/nova/tests/api/openstack/test_wsgi.py
@@ -256,6 +256,13 @@ class ResponseSerializerTest(test.TestCase):
self.assertEqual(response.body, 'pew_json')
self.assertEqual(response.status_int, 404)
+ def test_serialize_response_None(self):
+ response = self.serializer.serialize(None, 'application/json')
+ print response
+ self.assertEqual(response.headers['Content-Type'], 'application/json')
+ self.assertEqual(response.body, '')
+ self.assertEqual(response.status_int, 404)
+
def test_serialize_response_dict_to_unknown_content_type(self):
self.assertRaises(exception.InvalidContentType,
self.serializer.serialize,