From e0105efd2e7f17d1c09f4653fa898a2aae6f39f8 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 16:39:04 -0700 Subject: [PATCH 1/4] Set XML namespace when returning XML --- nova/wsgi.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nova/wsgi.py b/nova/wsgi.py index ba0819466..f0a60582d 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -478,6 +478,9 @@ class Serializer(object): root_key = data.keys()[0] doc = minidom.Document() node = self._to_xml_node(doc, metadata, root_key, data[root_key]) + node.setAttribute('xmlns', + 'http://docs.rackspacecloud.com/servers/api/v1.0') + return node.toprettyxml(indent=' ') def _to_xml_node(self, doc, metadata, nodename, data): From 49d22a4efb84dd1712a98b2d64838d270e74f6ef Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 16:59:03 -0700 Subject: [PATCH 2/4] Support setting the xmlns intelligently --- nova/wsgi.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/nova/wsgi.py b/nova/wsgi.py index f0a60582d..5d286bb3b 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -355,7 +355,8 @@ class Controller(object): if type(result) is dict: content_type = req.best_match_content_type() - body = self._serialize(result, content_type) + default_xmlns = self.get_default_xmlns(req) + body = self._serialize(result, content_type, default_xmlns) response = webob.Response() response.headers["Content-Type"] = content_type @@ -365,14 +366,15 @@ class Controller(object): else: return result - def _serialize(self, data, content_type): + def _serialize(self, data, content_type, default_xmlns): """ Serialize the given dict to the provided content_type. Uses self._serialization_metadata if it exists, which is a dict mapping MIME types to information needed to serialize to that type. """ _metadata = getattr(type(self), "_serialization_metadata", {}) - serializer = Serializer(_metadata) + + serializer = Serializer(_metadata, default_xmlns) try: return serializer.serialize(data, content_type) except exception.InvalidContentType: @@ -388,19 +390,23 @@ class Controller(object): serializer = Serializer(_metadata) return serializer.deserialize(data, content_type) + def get_default_xmlns(self, req): + return 'http://docs.rackspacecloud.com/servers/api/v1.0' + class Serializer(object): """ Serializes and deserializes dictionaries to certain MIME types. """ - def __init__(self, metadata=None): + def __init__(self, metadata=None, default_xmlns=None): """ Create a serializer based on the given WSGI environment. 'metadata' is an optional dict mapping MIME types to information needed to serialize a dictionary to that type. """ self.metadata = metadata or {} + self.default_xmlns = default_xmlns def _get_serialize_handler(self, content_type): handlers = { @@ -478,14 +484,23 @@ class Serializer(object): root_key = data.keys()[0] doc = minidom.Document() node = self._to_xml_node(doc, metadata, root_key, data[root_key]) - node.setAttribute('xmlns', - 'http://docs.rackspacecloud.com/servers/api/v1.0') + + xmlns = node.getAttribute('xmlns') + if not xmlns and self.default_xmlns: + node.setAttribute('xmlns', self.default_xmlns) return node.toprettyxml(indent=' ') def _to_xml_node(self, doc, metadata, nodename, data): """Recursive method to convert data members to XML nodes.""" result = doc.createElement(nodename) + + # Set the xml namespace if one is specified + # TODO(justinsb): We could also use prefixes on the keys + xmlns = metadata.get('xmlns', None) + if xmlns: + result.setAttribute('xmlns', xmlns) + if type(data) is list: singular = metadata.get('plurals', {}).get(nodename, None) if singular is None: From f21d2eb71f6f909fc3f01c0b1f6f518ba1458dd9 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 22 Mar 2011 21:18:31 -0700 Subject: [PATCH 3/4] Added note agreeing with Brian Lamar that the namespace doesn't belong in wsgi --- nova/wsgi.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nova/wsgi.py b/nova/wsgi.py index 5d286bb3b..1bcc08f7f 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -391,6 +391,10 @@ class Controller(object): return serializer.deserialize(data, content_type) def get_default_xmlns(self, req): + # NOTE(justinsb): This doesn't really belong here.. + # We'll probably end up moving this into a new OpenstackApiController + # class or something like that, once we know what's going to happen + # with v1.1 return 'http://docs.rackspacecloud.com/servers/api/v1.0' From 0356f63aa00502b26517c82ba76fcc5dfda08847 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 30 Mar 2011 10:05:06 -0700 Subject: [PATCH 4/4] Add XML namespaces to the OpenStack API --- nova/wsgi.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/nova/wsgi.py b/nova/wsgi.py index 1bcc08f7f..48502eebb 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -362,7 +362,6 @@ class Controller(object): response.headers["Content-Type"] = content_type response.body = body return response - else: return result @@ -391,11 +390,8 @@ class Controller(object): return serializer.deserialize(data, content_type) def get_default_xmlns(self, req): - # NOTE(justinsb): This doesn't really belong here.. - # We'll probably end up moving this into a new OpenstackApiController - # class or something like that, once we know what's going to happen - # with v1.1 - return 'http://docs.rackspacecloud.com/servers/api/v1.0' + """Provide the XML namespace to use if none is otherwise specified.""" + return None class Serializer(object):