summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorNaveed Massjouni <naveedm9@gmail.com>2011-07-21 15:08:46 -0400
committerNaveed Massjouni <naveedm9@gmail.com>2011-07-21 15:08:46 -0400
commitaf5c549d7795fcf9fdcb7d8e9193aa985f121fc6 (patch)
tree5b8dbd31fc11cf3086c0a0004a216d87efafb4d1 /nova
parent74c399cb2ebb914973c2f0dc6ecf4dd8bbc062d7 (diff)
Moving lp:~rackspace-titan/nova/extensions-xml-serialization to new branch based off of trunk. To remove dep on another branch.
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/extensions.py43
-rw-r--r--nova/api/openstack/wsgi.py4
-rw-r--r--nova/tests/api/openstack/test_extensions.py113
3 files changed, 152 insertions, 8 deletions
diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py
index da06ecd15..e500e51fa 100644
--- a/nova/api/openstack/extensions.py
+++ b/nova/api/openstack/extensions.py
@@ -23,6 +23,7 @@ import sys
import routes
import webob.dec
import webob.exc
+from xml.etree import ElementTree
from nova import exception
from nova import flags
@@ -194,7 +195,7 @@ class ExtensionsResource(wsgi.Resource):
def show(self, req, id):
# NOTE(dprince): the extensions alias is used as the 'id' for show
ext = self.extension_manager.extensions[id]
- return self._translate(ext)
+ return dict(extension=self._translate(ext))
def delete(self, req, id):
raise faults.Fault(webob.exc.HTTPNotFound())
@@ -258,15 +259,18 @@ class ExtensionMiddleware(base_wsgi.Middleware):
mapper = routes.Mapper()
+ serializer = wsgi.ResponseSerializer(
+ {'application/xml': ExtensionsXMLSerializer()})
# extended resources
for resource in ext_mgr.get_resources():
LOG.debug(_('Extended resource: %s'),
resource.collection)
mapper.resource(resource.collection, resource.collection,
- controller=wsgi.Resource(resource.controller),
- collection=resource.collection_actions,
- member=resource.member_actions,
- parent_resource=resource.parent)
+ controller=wsgi.Resource(
+ resource.controller, serializer=serializer),
+ collection=resource.collection_actions,
+ member=resource.member_actions,
+ parent_resource=resource.parent)
# extended actions
action_resources = self._action_ext_resources(application, ext_mgr,
@@ -462,3 +466,32 @@ class ResourceExtension(object):
self.parent = parent
self.collection_actions = collection_actions
self.member_actions = member_actions
+
+
+class ExtensionsXMLSerializer(wsgi.XMLDictSerializer):
+
+ def _add_extension_attributes(self, node, extension):
+ node.setAttribute('name', extension['name'])
+ node.setAttribute('namespace', extension['namespace'])
+ node.setAttribute('alias', extension['alias'])
+ node.setAttribute('updated', extension['updated'])
+
+ def show(self, ext_dict):
+ root = ElementTree.Element('extension');
+ extension = ext_dict['extension']
+ root.set('xmlns', wsgi.XMLNS_V11)
+ root.set('xmlns:atom', wsgi.XMLNS_ATOM)
+ root.set('name', extension['name'])
+ root.set('namespace', extension['namespace'])
+ root.set('alias', extension['alias'])
+ root.set('updated', extension['updated'])
+ desc = ElementTree.Element('description');
+ desc.text = extension['description']
+ root.append(desc)
+ for link in extension.get('links', []):
+ elem = ElementTree.Element('atom:link');
+ elem.set('rel', link['rel'])
+ elem.set('href', link['href'])
+ elem.set('type', link['type'])
+ root.append(elem)
+ return ElementTree.tostring(root)
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index 9df6fd058..d9993282f 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -13,6 +13,7 @@ from nova import wsgi
XMLNS_V10 = 'http://docs.rackspacecloud.com/servers/api/v1.0'
XMLNS_V11 = 'http://docs.openstack.org/compute/api/v1.1'
+XMLNS_ATOM = 'http://www.w3.org/2005/Atom'
LOG = logging.getLogger('nova.api.openstack.wsgi')
@@ -352,6 +353,9 @@ class XMLDictSerializer(DictSerializer):
link_node = xml_doc.createElement('atom:link')
link_node.setAttribute('rel', link['rel'])
link_node.setAttribute('href', link['href'])
+ if link.get('type'):
+ link_node.setAttribute('type', link['type'])
+
link_nodes.append(link_node)
return link_nodes
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index 697c62e5c..6d3c1b1be 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -16,10 +16,11 @@
# under the License.
import json
+import os.path
import stubout
import unittest
import webob
-import os.path
+from xml.etree import ElementTree
from nova import context
from nova import flags
@@ -80,19 +81,73 @@ class StubExtensionManager(object):
class ExtensionControllerTest(unittest.TestCase):
- def test_index(self):
+ def setUp(self):
+ FLAGS.osapi_extensions_path = os.path.join(
+ os.path.dirname(__file__), "extensions")
+
+ def test_list_extensions_json(self):
app = openstack.APIRouterV11()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/extensions")
response = request.get_response(ext_midware)
self.assertEqual(200, response.status_int)
- def test_get_by_alias(self):
+ # Make sure we have all the extensions.
+ data = json.loads(response.body)
+ names = [x['name'] for x in data['extensions']]
+ names.sort()
+ self.assertEqual(names, ["FlavorExtraSpecs", "Floating_ips",
+ "Fox In Socks", "Hosts", "Multinic", "Volumes"])
+
+ # Make sure that at least Fox in Sox is correct.
+ (fox_ext,) = [
+ x for x in data['extensions'] if x['alias'] == 'FOXNSOX']
+ self.assertEqual(fox_ext, {
+ "namespace" : "http://www.fox.in.socks/api/ext/pie/v1.0",
+ "name" : "Fox In Socks",
+ "updated" : "2011-01-22T13:25:27-06:00",
+ "description" : "The Fox In Socks Extension",
+ "alias" : "FOXNSOX",
+ "links" : []
+ }
+ )
+
+ def test_get_extension_json(self):
+ app = openstack.APIRouterV11()
+ ext_midware = extensions.ExtensionMiddleware(app)
+ request = webob.Request.blank("/extensions/FOXNSOX")
+ response = request.get_response(ext_midware)
+ self.assertEqual(200, response.status_int)
+
+ data = json.loads(response.body)
+ self.assertEqual(data['extension'], {
+ "namespace" : "http://www.fox.in.socks/api/ext/pie/v1.0",
+ "name" : "Fox In Socks",
+ "updated" : "2011-01-22T13:25:27-06:00",
+ "description" : "The Fox In Socks Extension",
+ "alias" : "FOXNSOX",
+ "links" : []
+ }
+ )
+
+ def test_get_extension_xml(self):
app = openstack.APIRouterV11()
ext_midware = extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/extensions/FOXNSOX")
+ request.accept = "application/xml"
response = request.get_response(ext_midware)
self.assertEqual(200, response.status_int)
+ print response.body
+
+ elem = ElementTree.XML(response.body.replace(" ", ""))
+ self.assertEqual(elem.get('alias'), 'FOXNSOX')
+ self.assertEqual(elem.get('name'), 'Fox In Socks')
+ self.assertEqual(elem.get('namespace'),
+ 'http://www.fox.in.socks/api/ext/pie/v1.0')
+ self.assertEqual(elem.get('updated'), '2011-01-22T13:25:27-06:00')
+ ns = "{http://docs.openstack.org/compute/api/v1.1}"
+ self.assertEqual(elem.findtext('{0}description'.format(ns)),
+ 'The Fox In Socks Extension')
class ResourceExtensionTest(unittest.TestCase):
@@ -244,3 +299,55 @@ class RequestExtensionTest(unittest.TestCase):
response_data = json.loads(response.body)
self.assertEqual('newblue', response_data['flavor']['googoose'])
self.assertEqual("Pig Bands!", response_data['big_bands'])
+
+class ExtensionsXMLSerializerTest(unittest.TestCase):
+ def test_serialize(self):
+ serializer = extensions.ExtensionsXMLSerializer()
+ data = {
+ 'extension': {
+ 'name': 'ext1',
+ "namespace" : "http://docs.rack.com/servers/api/ext/pie/v1.0",
+ "alias" : "RS-PIE",
+ "updated" : "2011-01-22T13:25:27-06:00",
+ "description" : "Adds the capability to share an image.",
+ "links" : [
+ {
+ "rel" : "describedby",
+ "type" : "application/pdf",
+ "href" : "http://docs.rack.com/servers/api/ext/cs.pdf"
+ },
+ {
+ "rel" : "describedby",
+ "type" : "application/vnd.sun.wadl+xml",
+ "href" : "http://docs.rack.com/servers/api/ext/cs.wadl"
+ }
+ ]
+ },
+ }
+
+ ns = "{http://docs.openstack.org/compute/api/v1.1}"
+ atomns = "{http://www.w3.org/2005/Atom}"
+ elem = ElementTree.XML(serializer.serialize(data, 'show'))
+ self.assertEqual(elem.tag.split('extension')[0], ns)
+ self.assertEqual(elem.get('alias'), 'RS-PIE')
+ self.assertEqual(elem.get('name'), 'ext1')
+ self.assertEqual(elem.get('namespace'),
+ 'http://docs.rack.com/servers/api/ext/pie/v1.0')
+ self.assertEqual(elem.get('updated'), '2011-01-22T13:25:27-06:00')
+ self.assertEqual(elem.findtext('{0}description'.format(ns)),
+ 'Adds the capability to share an image.')
+
+ link_nodes = elem.findall('{0}link'.format(atomns))
+ self.assertEqual(len(link_nodes), 2)
+ link_nodes.sort(key=lambda x: x.get('type'))
+
+ self.assertEqual(link_nodes[0].get('type'), 'application/pdf')
+ self.assertEqual(link_nodes[0].get('rel'), 'describedby')
+ self.assertEqual(link_nodes[0].get('href'),
+ 'http://docs.rack.com/servers/api/ext/cs.pdf')
+
+ self.assertEqual(link_nodes[1].get('type'),
+ 'application/vnd.sun.wadl+xml')
+ self.assertEqual(link_nodes[1].get('rel'), 'describedby')
+ self.assertEqual(link_nodes[1].get('href'),
+ 'http://docs.rack.com/servers/api/ext/cs.wadl')