From 0e2726f452fe6991797728bca1e514943725e7a2 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Fri, 22 Jul 2011 10:34:01 -0400 Subject: initial test for v1.1 detail request --- nova/tests/api/openstack/test_versions.py | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 0eae18a62..aaa1f4976 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -16,6 +16,7 @@ # under the License. import json +import stubout import webob from nova import context @@ -29,6 +30,9 @@ class VersionsTest(test.TestCase): def setUp(self): super(VersionsTest, self).setUp() self.context = context.get_admin_context() + self.stubs = stubout.StubOutForTesting() + fakes.stub_out_auth(self.stubs) + def tearDown(self): super(VersionsTest, self).tearDown() @@ -64,6 +68,55 @@ class VersionsTest(test.TestCase): ] self.assertEqual(versions, expected) + def test_get_version_1_1_detail(self): + req = webob.Request.blank('/v1.1/') + req.accept = "application/json" + res = req.get_response(fakes.wsgi_app()) + print res.body + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/json") + versions = json.loads(res.body)["versions"] + expected = [ + { + "version" : { + "id" : "v1.1", + "status" : "CURRENT", + "updated" : "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel" : "self", + "href" : "http://servers.api.openstack.org/v1.0/" + }, + { + "rel" : "describedby", + "type" : "application/pdf", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel" : "describedby", + "type" : "application/vnd.sun.wadl+xml", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + } + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/" + "vnd.openstack.compute-v1.1+xml" + }, + { + "base" : "application/json", + "type" : "application/" + "vnd.openstack.compute-v1.1+json" + } + ] + } + } + ] + self.assertEqual(versions, expected) + def test_get_version_list_xml(self): req = webob.Request.blank('/') req.accept = "application/xml" -- cgit From 99bc14f16bce9f125715fbe436b7fc0969b62420 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 25 Jul 2011 14:10:08 -0400 Subject: added 1.0 detail test, added VersionRequestDeserializer to support Versions actions properly, started 300/multiple choice work --- nova/api/openstack/__init__.py | 6 ++ nova/api/openstack/versions.py | 92 ++++++++++++++++++++++++++++++- nova/tests/api/openstack/test_versions.py | 51 ++++++++++++++++- 3 files changed, 145 insertions(+), 4 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index e87d7c754..fb6f5515e 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -40,6 +40,7 @@ from nova.api.openstack import servers from nova.api.openstack import server_metadata from nova.api.openstack import shared_ip_groups from nova.api.openstack import users +from nova.api.openstack import versions from nova.api.openstack import wsgi from nova.api.openstack import zones @@ -115,6 +116,10 @@ class APIRouter(base_wsgi.Router): 'select': 'POST', 'boot': 'POST'}) + mapper.connect("versions", "/", + controller=versions.create_resource(version), + action="index") + mapper.resource("console", "consoles", controller=consoles.create_resource(), parent_resource=dict(member_name='server', @@ -164,6 +169,7 @@ 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(), parent_resource=dict(member_name='image', diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index df7a94b7e..445a14372 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -28,6 +28,13 @@ ATOM_XMLNS = "http://www.w3.org/2005/Atom" class Versions(wsgi.Resource): + @classmethod + def factory(cls, global_config, **local_config): + """Paste factory.""" + def _factory(app): + return cls(app, **local_config) + return _factory + def __init__(self): metadata = { "attributes": { @@ -45,7 +52,7 @@ class Versions(wsgi.Resource): supported_content_types = ('application/json', 'application/xml', 'application/atom+xml') - deserializer = wsgi.RequestDeserializer( + deserializer = VersionsRequestDeserializer( supported_content_types=supported_content_types) wsgi.Resource.__init__(self, None, serializer=serializer, @@ -53,6 +60,14 @@ class Versions(wsgi.Resource): def dispatch(self, request, *args): """Respond to a request for all OpenStack API versions.""" + if request.path == '/': + # List Versions + return self._versions_list(request) + else: + # Versions Multiple Choice + return self._versions_multi_choice(request) + + def _versions_list(self, request): version_objs = [ { "id": "v1.1", @@ -72,6 +87,47 @@ class Versions(wsgi.Resource): versions = [builder.build(version) for version in version_objs] return dict(versions=versions) + def _versions_multi_choice(self, request): + version_objs = [ + { + "id": "v1.1", + "status": "CURRENT", + #TODO(wwolf) get correct value for these + "updated": "2011-07-18T11:30:00Z", + }, + { + "id": "v1.0", + "status": "DEPRECATED", + #TODO(wwolf) get correct value for these + "updated": "2010-10-09T11:30:00Z", + }, + ] + + builder = nova.api.openstack.views.versions.get_view_builder(request) + versions = [builder.build(version) for version in version_objs] + return dict(versions=versions) + + +class VersionV10(object): + def index(self, req): + return "test index 1.0" + + +class VersionV11(object): + def index(self, req): + return "test index 1.1" + +class VersionsRequestDeserializer(wsgi.RequestDeserializer): + def get_action_args(self, request_environment): + """Parse dictionary created by routes library.""" + + args = {} + if request_environment['PATH_INFO'] == '/': + args['action'] = 'index' + else: + args['action'] = 'multi' + + return args class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _versions_to_xml(self, versions): @@ -96,7 +152,13 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return version_node - def default(self, data): + def index(self, data): + self._xml_doc = minidom.Document() + node = self._versions_to_xml(data['versions']) + + return self.to_xml_string(node) + + def multi(self, data): self._xml_doc = minidom.Document() node = self._versions_to_xml(data['versions']) @@ -190,10 +252,34 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): entry.appendChild(content) root.appendChild(entry) - def default(self, data): + def index(self, data): self._xml_doc = minidom.Document() node = self._xml_doc.createElementNS(self.xmlns, 'feed') self._create_meta(node, data['versions']) self._create_version_entries(node, data['versions']) return self.to_xml_string(node) + + def multi(self, data): + self._xml_doc = minidom.Document() + node = self._xml_doc.createElementNS(self.xmlns, 'feed') + self._create_meta(node, data['versions']) + self._create_version_entries(node, data['versions']) + + return self.to_xml_string(node) + + +def create_resource(version='1.0'): + controller = { + '1.0': VersionV10, + '1.1': VersionV11, + }[version]() + + body_serializers = { + 'application/xml': VersionsXMLSerializer(), + 'application/atom+xml': VersionsAtomSerializer(), + } + + serializer = wsgi.ResponseSerializer(body_serializers) + + return wsgi.Resource(controller, serializer=serializer) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index aaa1f4976..b2896a780 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -68,6 +68,55 @@ class VersionsTest(test.TestCase): ] self.assertEqual(versions, expected) + def test_get_version_1_0_detail(self): + req = webob.Request.blank('/v1.0/') + req.accept = "application/json" + res = req.get_response(fakes.wsgi_app()) + print res.body + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/json") + versions = json.loads(res.body)["versions"] + expected = [ + { + "version" : { + "id" : "v1.0", + "status" : "CURRENT", + "updated" : "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel" : "self", + "href" : "http://servers.api.openstack.org/v1.0/" + }, + { + "rel" : "describedby", + "type" : "application/pdf", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel" : "describedby", + "type" : "application/vnd.sun.wadl+xml", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + } + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/" + "vnd.openstack.compute-v1.0+xml" + }, + { + "base" : "application/json", + "type" : "application/" + "vnd.openstack.compute-v1.0+json" + } + ] + } + } + ] + self.assertEqual(versions, expected) + def test_get_version_1_1_detail(self): req = webob.Request.blank('/v1.1/') req.accept = "application/json" @@ -85,7 +134,7 @@ class VersionsTest(test.TestCase): "links": [ { "rel" : "self", - "href" : "http://servers.api.openstack.org/v1.0/" + "href" : "http://servers.api.openstack.org/v1.1/" }, { "rel" : "describedby", -- cgit From 810d4b89cbbfa9388fb61f9069ea0104a7d77752 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 25 Jul 2011 15:28:06 -0400 Subject: removed prints, got versions detail tests passing, still need to do xml/atom --- nova/api/openstack/__init__.py | 2 +- nova/api/openstack/versions.py | 96 ++++++++-- nova/tests/api/openstack/test_versions.py | 295 +++++++++++++++++++++--------- 3 files changed, 292 insertions(+), 101 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index fb6f5515e..a6a8b4595 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -118,7 +118,7 @@ class APIRouter(base_wsgi.Router): mapper.connect("versions", "/", controller=versions.create_resource(version), - action="index") + action="detail") mapper.resource("console", "consoles", controller=consoles.create_resource(), diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 445a14372..5655edcfc 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -88,6 +88,7 @@ class Versions(wsgi.Resource): return dict(versions=versions) def _versions_multi_choice(self, request): + #TODO version_objs = [ { "id": "v1.1", @@ -109,18 +110,87 @@ class Versions(wsgi.Resource): class VersionV10(object): - def index(self, req): - return "test index 1.0" + def detail(self, req): + #TODO + return { + "version" : { + "id": "v1.0", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.0/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.0+json" + } + ], + }, + } class VersionV11(object): - def index(self, req): - return "test index 1.1" + def detail(self, req): + return { + "version" : { + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.1/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.1+json" + } + ], + }, + } + class VersionsRequestDeserializer(wsgi.RequestDeserializer): def get_action_args(self, request_environment): """Parse dictionary created by routes library.""" - args = {} if request_environment['PATH_INFO'] == '/': args['action'] = 'index' @@ -129,6 +199,7 @@ class VersionsRequestDeserializer(wsgi.RequestDeserializer): return args + class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _versions_to_xml(self, versions): root = self._xml_doc.createElement('versions') @@ -158,6 +229,9 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) + def detail(self,data): + return "" + def multi(self, data): self._xml_doc = minidom.Document() node = self._versions_to_xml(data['versions']) @@ -167,6 +241,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): class VersionsAtomSerializer(wsgi.XMLDictSerializer): def __init__(self, metadata=None, xmlns=None): + self.metadata = metadata or {} if not xmlns: self.xmlns = ATOM_XMLNS else: @@ -260,14 +335,9 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) - def multi(self, data): - self._xml_doc = minidom.Document() - node = self._xml_doc.createElementNS(self.xmlns, 'feed') - self._create_meta(node, data['versions']) - self._create_version_entries(node, data['versions']) - - return self.to_xml_string(node) - + def detail(self, data): + #TODO + pass def create_resource(version='1.0'): controller = { diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index b2896a780..9c4af0787 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -72,99 +72,132 @@ class VersionsTest(test.TestCase): req = webob.Request.blank('/v1.0/') req.accept = "application/json" res = req.get_response(fakes.wsgi_app()) - print res.body self.assertEqual(res.status_int, 200) self.assertEqual(res.content_type, "application/json") - versions = json.loads(res.body)["versions"] - expected = [ - { - "version" : { - "id" : "v1.0", - "status" : "CURRENT", - "updated" : "2011-01-21T11:33:21-06:00", - "links": [ - { - "rel" : "self", - "href" : "http://servers.api.openstack.org/v1.0/" - }, - { - "rel" : "describedby", - "type" : "application/pdf", - "href" : "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" - }, - { - "rel" : "describedby", - "type" : "application/vnd.sun.wadl+xml", - "href" : "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" - } - ], - "media-types": [ - { - "base" : "application/xml", - "type" : "application/" - "vnd.openstack.compute-v1.0+xml" - }, - { - "base" : "application/json", - "type" : "application/" - "vnd.openstack.compute-v1.0+json" - } - ] - } + version = json.loads(res.body) + expected = { + "version" : { + "id" : "v1.0", + "status" : "CURRENT", + "updated" : "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel" : "self", + "href" : "http://servers.api.openstack.org/v1.0/" + }, + { + "rel" : "describedby", + "type" : "application/pdf", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel" : "describedby", + "type" : "application/vnd.sun.wadl+xml", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + } + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/" + "vnd.openstack.compute-v1.0+xml" + }, + { + "base" : "application/json", + "type" : "application/" + "vnd.openstack.compute-v1.0+json" + } + ] } - ] - self.assertEqual(versions, expected) + } + self.assertEqual(expected, version) def test_get_version_1_1_detail(self): req = webob.Request.blank('/v1.1/') req.accept = "application/json" res = req.get_response(fakes.wsgi_app()) - print res.body self.assertEqual(res.status_int, 200) self.assertEqual(res.content_type, "application/json") - versions = json.loads(res.body)["versions"] - expected = [ - { - "version" : { - "id" : "v1.1", - "status" : "CURRENT", - "updated" : "2011-01-21T11:33:21-06:00", - "links": [ - { - "rel" : "self", - "href" : "http://servers.api.openstack.org/v1.1/" - }, - { - "rel" : "describedby", - "type" : "application/pdf", - "href" : "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" - }, - { - "rel" : "describedby", - "type" : "application/vnd.sun.wadl+xml", - "href" : "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" - } - ], - "media-types": [ - { - "base" : "application/xml", - "type" : "application/" - "vnd.openstack.compute-v1.1+xml" - }, - { - "base" : "application/json", - "type" : "application/" - "vnd.openstack.compute-v1.1+json" - } - ] - } + version = json.loads(res.body) + expected = { + "version" : { + "id" : "v1.1", + "status" : "CURRENT", + "updated" : "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel" : "self", + "href" : "http://servers.api.openstack.org/v1.1/" + }, + { + "rel" : "describedby", + "type" : "application/pdf", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel" : "describedby", + "type" : "application/vnd.sun.wadl+xml", + "href" : "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + } + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/" + "vnd.openstack.compute-v1.1+xml" + }, + { + "base" : "application/json", + "type" : "application/" + "vnd.openstack.compute-v1.1+json" + } + ] } - ] - self.assertEqual(versions, expected) + } + self.assertEqual(expected, version) + + def test_get_version_1_0_detail_xml(self): + pass + + def test_get_version_1_1_detail_xml(self): + req = webob.Request.blank('/v1.1/') + req.accept = "application/xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/xml") + expected = """ + + + + + + + + + + + + + + """.replace(" ", "").replace("\n", "") + + actual = res.body.replace(" ", "").replace("\n", "") + self.assertEqual(expected, actual) def test_get_version_list_xml(self): req = webob.Request.blank('/') @@ -265,7 +298,37 @@ class VersionsTest(test.TestCase): self.assertEqual(actual, expected) - def test_xml_serializer(self): + def test_versions_list_xml_serializer(self): + versions_data = { + 'versions': [ + { + "id": "2.7.1", + "updated": "2011-07-18T11:30:00Z", + "status": "DEPRECATED", + "links": [ + { + "rel": "self", + "href": "http://test/2.7.1", + } + ], + }, + ] + } + + expected = """ + + + + + """.replace(" ", "").replace("\n", "") + + serializer = versions.VersionsXMLSerializer() + response = serializer.index(versions_data) + response = response.replace(" ", "").replace("\n", "") + self.assertEqual(expected, response) + + def test_versions_detail_xml_serializer(self): versions_data = { 'versions': [ { @@ -291,11 +354,70 @@ class VersionsTest(test.TestCase): """.replace(" ", "").replace("\n", "") serializer = versions.VersionsXMLSerializer() - response = serializer.default(versions_data) + response = serializer.index(versions_data) + response = response.replace(" ", "").replace("\n", "") + self.assertEqual(expected, response) + + def test_versions_list_atom_serializer(self): + versions_data = { + 'versions': [ + { + "id": "2.9.8", + "updated": "2011-07-20T11:40:00Z", + "status": "CURRENT", + "links": [ + { + "rel": "self", + "href": "http://test/2.9.8", + } + ], + }, + ] + } + + expected = """ + + + Available API Versions + + + 2011-07-20T11:40:00Z + + + http://test/ + + + + Rackspace + + + http://www.rackspace.com/ + + + + + + http://test/2.9.8 + + + Version 2.9.8 + + + 2011-07-20T11:40:00Z + + + + Version 2.9.8 CURRENT (2011-07-20T11:40:00Z) + + + """.replace(" ", "").replace("\n", "") + + serializer = versions.VersionsAtomSerializer() + response = serializer.index(versions_data) response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) - def test_atom_serializer(self): + def test_version_detail_atom_serializer(self): versions_data = { 'versions': [ { @@ -350,7 +472,6 @@ class VersionsTest(test.TestCase): """.replace(" ", "").replace("\n", "") serializer = versions.VersionsAtomSerializer() - response = serializer.default(versions_data) - print response + response = serializer.index(versions_data) response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) -- cgit From 71a103822b41df3d90a1e958baffda55a9cb8730 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 25 Jul 2011 16:25:19 -0400 Subject: xml version detail working with tests --- nova/api/openstack/versions.py | 30 +++++- nova/tests/api/openstack/test_versions.py | 165 +++++++++++++++++++++--------- 2 files changed, 147 insertions(+), 48 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 5655edcfc..00fc8d98f 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -209,16 +209,39 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return root - def _create_version_node(self, version): + def _create_media_types(self, media_types): + base = self._xml_doc.createElement('media-types') + for type in media_types: + node = self._xml_doc.createElement('media-type') + node.setAttribute('base', type['base']) + node.setAttribute('type', type['type']) + base.appendChild(node) + + return base + + def _create_version_node(self, version, create_ns=False): version_node = self._xml_doc.createElement('version') + if create_ns: + xmlns = "http://docs.openstack.org/common/api/%s" % version['id'] + xmlns_atom = "http://www.w3.org/2005/Atom" + version_node.setAttribute('xmlns', xmlns) + version_node.setAttribute('xmlns:atom', xmlns_atom) + version_node.setAttribute('id', version['id']) version_node.setAttribute('status', version['status']) version_node.setAttribute('updated', version['updated']) + if 'media-types' in version: + media_types = self._create_media_types(version['media-types']) + version_node.appendChild(media_types) + for link in version['links']: link_node = self._xml_doc.createElement('atom:link') link_node.setAttribute('rel', link['rel']) link_node.setAttribute('href', link['href']) + if 'type' in link: + link_node.setAttribute('type', link['type']) + version_node.appendChild(link_node) return version_node @@ -230,7 +253,10 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) def detail(self,data): - return "" + self._xml_doc = minidom.Document() + node = self._create_version_node(data['version'], True) + + return self.to_xml_string(node) def multi(self, data): self._xml_doc = minidom.Document() diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 9c4af0787..632d388fa 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -161,7 +161,40 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, version) def test_get_version_1_0_detail_xml(self): - pass + req = webob.Request.blank('/v1.0/') + req.accept = "application/xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/xml") + expected = """ + + + + + + + + + + + + + """.replace(" ", "").replace("\n", "") + + actual = res.body.replace(" ", "").replace("\n", "") + self.assertEqual(expected, actual) def test_get_version_1_1_detail_xml(self): req = webob.Request.blank('/v1.1/') @@ -170,31 +203,31 @@ class VersionsTest(test.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res.content_type, "application/xml") expected = """ - - - - - - - - - - - - - - """.replace(" ", "").replace("\n", "") + + + + + + + + + + + + + """.replace(" ", "").replace("\n", "") actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -330,31 +363,70 @@ class VersionsTest(test.TestCase): def test_versions_detail_xml_serializer(self): versions_data = { - 'versions': [ - { - "id": "2.7.1", - "updated": "2011-07-18T11:30:00Z", - "status": "DEPRECATED", - "links": [ - { - "rel": "self", - "href": "http://test/2.7.1", - } - ], - }, - ] + "version" : { + "id": "v1.0", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21-06:00", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.0/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.0+json" + } + ], + }, } expected = """ - - - - - """.replace(" ", "").replace("\n", "") + + + + + + + + + + + + + """.replace(" ", "").replace("\n", "") serializer = versions.VersionsXMLSerializer() - response = serializer.index(versions_data) + response = serializer.detail(versions_data) response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) @@ -418,6 +490,7 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, response) def test_version_detail_atom_serializer(self): + #TODO versions_data = { 'versions': [ { -- cgit From 7be2b2482fde20be8802cfe6a200590933a73d7e Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 25 Jul 2011 18:28:43 -0400 Subject: atom and xml_detail working, with tests --- nova/api/openstack/versions.py | 49 ++++++-- nova/tests/api/openstack/test_versions.py | 200 +++++++++++++++++++++--------- 2 files changed, 183 insertions(+), 66 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 00fc8d98f..6fba4bbe0 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -116,7 +116,7 @@ class VersionV10(object): "version" : { "id": "v1.0", "status": "CURRENT", - "updated": "2011-01-21T11:33:21-06:00", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -155,7 +155,7 @@ class VersionV11(object): "version" : { "id": "v1.1", "status": "CURRENT", - "updated": "2011-01-21T11:33:21-06:00", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -298,8 +298,33 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): link_href = link_href.rstrip('/') return link_href.rsplit('/', 1)[0] + '/' - def _create_meta(self, root, versions): - title = self._create_text_elem('title', 'Available API Versions', + def _create_detail_meta(self, root, version): + title = self._create_text_elem('title', "About This Version", + type='text') + + updated = self._create_text_elem('updated', version['updated']) + + uri = version['links'][0]['href'] + id = self._create_text_elem('id', uri) + + link = self._xml_doc.createElement('link') + link.setAttribute('rel', 'self') + link.setAttribute('href', uri) + + author = self._xml_doc.createElement('author') + author_name = self._create_text_elem('name', 'Rackspace') + author_uri = self._create_text_elem('uri', 'http://www.rackspace.com/') + author.appendChild(author_name) + author.appendChild(author_uri) + + root.appendChild(title) + root.appendChild(updated) + root.appendChild(id) + root.appendChild(author) + root.appendChild(link) + + def _create_list_meta(self, root, versions): + title = self._create_text_elem('title', "Available API Versions", type='text') # Set this updated to the most recently updated version recent = self._get_most_recent_update(versions) @@ -307,6 +332,7 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): base_url = self._get_base_url(versions[0]['links'][0]['href']) id = self._create_text_elem('id', base_url) + link = self._xml_doc.createElement('link') link.setAttribute('rel', 'self') link.setAttribute('href', base_url) @@ -341,7 +367,10 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): link_node = self._xml_doc.createElement('link') link_node.setAttribute('rel', link['rel']) link_node.setAttribute('href', link['href']) - entry.appendChild(link_node) + if 'type' in link: + link_node.setAttribute('type', link['type']) + + entry.appendChild(link_node) content = self._create_text_elem('content', 'Version %s %s (%s)' % @@ -356,14 +385,18 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): def index(self, data): self._xml_doc = minidom.Document() node = self._xml_doc.createElementNS(self.xmlns, 'feed') - self._create_meta(node, data['versions']) + self._create_list_meta(node, data['versions']) self._create_version_entries(node, data['versions']) return self.to_xml_string(node) def detail(self, data): - #TODO - pass + self._xml_doc = minidom.Document() + node = self._xml_doc.createElementNS(self.xmlns, 'feed') + self._create_detail_meta(node, data['version']) + self._create_version_entries(node, [data['version']]) + + return self.to_xml_string(node) def create_resource(version='1.0'): controller = { diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 632d388fa..11b69ec83 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -79,7 +79,7 @@ class VersionsTest(test.TestCase): "version" : { "id" : "v1.0", "status" : "CURRENT", - "updated" : "2011-01-21T11:33:21-06:00", + "updated" : "2011-01-21T11:33:21Z", "links": [ { "rel" : "self", @@ -125,7 +125,7 @@ class VersionsTest(test.TestCase): "version" : { "id" : "v1.1", "status" : "CURRENT", - "updated" : "2011-01-21T11:33:21-06:00", + "updated" : "2011-01-21T11:33:21Z", "links": [ { "rel" : "self", @@ -168,7 +168,7 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/xml") expected = """ @@ -204,7 +204,7 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/xml") expected = """ @@ -253,6 +253,80 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, actual) + def test_get_version_1_0_detail_atom(self): + #TODO + req = webob.Request.blank('/v1.0/') + req.accept = "application/xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/xml") + expected = """ + + + + + + + + + + + + + """.replace(" ", "").replace("\n", "") + + actual = res.body.replace(" ", "").replace("\n", "") + self.assertEqual(expected, actual) + + def test_get_version_1_1_detail_atom(self): + #TODO + req = webob.Request.blank('/v1.1/') + req.accept = "application/xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/xml") + expected = """ + + + + + + + + + + + + + """.replace(" ", "").replace("\n", "") + + actual = res.body.replace(" ", "").replace("\n", "") + self.assertEqual(expected, actual) + def test_get_version_list_atom(self): req = webob.Request.blank('/') req.accept = "application/atom+xml" @@ -361,12 +435,12 @@ class VersionsTest(test.TestCase): response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) - def test_versions_detail_xml_serializer(self): - versions_data = { + def test_version_detail_xml_serializer(self): + version_data = { "version" : { "id": "v1.0", "status": "CURRENT", - "updated": "2011-01-21T11:33:21-06:00", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -400,7 +474,7 @@ class VersionsTest(test.TestCase): expected = """ @@ -426,7 +500,7 @@ class VersionsTest(test.TestCase): """.replace(" ", "").replace("\n", "") serializer = versions.VersionsXMLSerializer() - response = serializer.detail(versions_data) + response = serializer.detail(version_data) response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) @@ -492,59 +566,69 @@ class VersionsTest(test.TestCase): def test_version_detail_atom_serializer(self): #TODO versions_data = { - 'versions': [ - { - "id": "2.9.8", - "updated": "2011-07-20T11:40:00Z", - "status": "CURRENT", - "links": [ - { - "rel": "self", - "href": "http://test/2.9.8", - } - ], - }, - ] + "version" : { + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.1/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.1+json" + } + ], + }, } expected = """ - - - Available API Versions - - - 2011-07-20T11:40:00Z - - - http://test/ - - - - Rackspace - - - http://www.rackspace.com/ - - - - - - http://test/2.9.8 - - - Version 2.9.8 - - - 2011-07-20T11:40:00Z - - - - Version 2.9.8 CURRENT (2011-07-20T11:40:00Z) - - - """.replace(" ", "").replace("\n", "") + + About This Version + 2011-01-21T11:33:21Z + http://servers.api.openstack.org/v1.1/ + + Rackspace + http://www.rackspace.com/ + + + + http://servers.api.openstack.org/v1.1/ + Version v1.1 + 2011-01-21T11:33:21Z + + + + + Version v1.1 CURRENT (2011-01-21T11:33:21Z) + + + """.replace(" ", "").replace("\n", "") serializer = versions.VersionsAtomSerializer() - response = serializer.index(versions_data) + response = serializer.detail(versions_data) response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) -- cgit From 4236f438a81e361beb1b05edd87154b4d5e1ce85 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Mon, 25 Jul 2011 22:38:59 +0000 Subject: Pass on auth_token --- nova/context.py | 4 +++- nova/image/glance.py | 11 +++++++++++ nova/tests/glance/stubs.py | 5 ++++- nova/tests/image/test_glance.py | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/nova/context.py b/nova/context.py index 99085ed75..a765d1695 100644 --- a/nova/context.py +++ b/nova/context.py @@ -32,7 +32,8 @@ class RequestContext(object): """ def __init__(self, user, project, is_admin=None, read_deleted=False, - remote_address=None, timestamp=None, request_id=None): + remote_address=None, timestamp=None, request_id=None, + auth_token=None): if hasattr(user, 'id'): self._user = user self.user_id = user.id @@ -63,6 +64,7 @@ class RequestContext(object): chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-' request_id = ''.join([random.choice(chars) for x in xrange(20)]) self.request_id = request_id + self.auth_token = auth_token @property def user(self): diff --git a/nova/image/glance.py b/nova/image/glance.py index 5c2dc957b..44a3c6f83 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -83,11 +83,16 @@ class GlanceImageService(service.BaseImageService): client = property(_get_client, _set_client) + def _set_client_context(self, context): + """Sets the client's auth token.""" + self.client.set_auth_token(context.auth_token) + def index(self, context, filters=None, marker=None, limit=None): """Calls out to Glance for a list of images available.""" # NOTE(sirp): We need to use `get_images_detailed` and not # `get_images` here because we need `is_public` and `properties` # included so we can filter by user + self._set_client_context(context) filtered = [] filters = filters or {} if 'is_public' not in filters: @@ -104,6 +109,7 @@ class GlanceImageService(service.BaseImageService): def detail(self, context, filters=None, marker=None, limit=None): """Calls out to Glance for a list of detailed image information.""" + self._set_client_context(context) filtered = [] filters = filters or {} if 'is_public' not in filters: @@ -120,6 +126,7 @@ class GlanceImageService(service.BaseImageService): def show(self, context, image_id): """Returns a dict with image data for the given opaque image id.""" + self._set_client_context(context) try: image_meta = self.client.get_image_meta(image_id) except glance_exception.NotFound: @@ -143,6 +150,7 @@ class GlanceImageService(service.BaseImageService): def get(self, context, image_id, data): """Calls out to Glance for metadata and data and writes data.""" + self._set_client_context(context) try: image_meta, image_chunks = self.client.get_image(image_id) except glance_exception.NotFound: @@ -160,6 +168,7 @@ class GlanceImageService(service.BaseImageService): :raises: AlreadyExists if the image already exist. """ + self._set_client_context(context) # Translate Base -> Service LOG.debug(_('Creating image in Glance. Metadata passed in %s'), image_meta) @@ -182,6 +191,7 @@ class GlanceImageService(service.BaseImageService): :raises: ImageNotFound if the image does not exist. """ + self._set_client_context(context) # NOTE(vish): show is to check if image is available self.show(context, image_id) try: @@ -198,6 +208,7 @@ class GlanceImageService(service.BaseImageService): :raises: ImageNotFound if the image does not exist. """ + self._set_client_context(context) # NOTE(vish): show is to check if image is available self.show(context, image_id) try: diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index aac3ff330..d51b19ccd 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -60,7 +60,10 @@ class FakeGlance(object): 'container_format': 'ovf'}, 'image_data': StringIO.StringIO('')}} - def __init__(self, host, port=None, use_ssl=False): + def __init__(self, host, port=None, use_ssl=False, auth_tok=None): + pass + + def set_auth_token(self, auth_tok): pass def get_image_meta(self, image_id): diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 223e7ae57..5a40f578f 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -31,6 +31,9 @@ class StubGlanceClient(object): self.add_response = add_response self.update_response = update_response + def set_auth_token(self, auth_tok): + pass + def get_image_meta(self, image_id): return self.images[image_id] -- cgit From eba09454a21ce49afa821ec63ed801883354ff7e Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 25 Jul 2011 20:34:41 -0400 Subject: initial stuff to get away from string comparisons for XML, and use ElementTree --- nova/api/openstack/versions.py | 7 ++ nova/tests/api/openstack/test_versions.py | 109 +++++++++++++++++++++++------- 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 6fba4bbe0..c250dac8c 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -201,6 +201,13 @@ class VersionsRequestDeserializer(wsgi.RequestDeserializer): class VersionsXMLSerializer(wsgi.XMLDictSerializer): + #TODO(wwolf): this is temporary until we get rid of toprettyxml + # in the base class (XMLDictSerializer), which I plan to do in + # another branch + def to_xml_string(self, node, has_atom=False): + self._add_xmlns(node, has_atom) + return node.toxml(encoding='UTF-8') + def _versions_to_xml(self, versions): root = self._xml_doc.createElement('versions') diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 11b69ec83..31b201214 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -18,6 +18,8 @@ import json import stubout import webob +import xml.etree.ElementTree + from nova import context from nova import test @@ -166,6 +168,21 @@ class VersionsTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) self.assertEqual(res.content_type, "application/xml") + root = xml.etree.ElementTree.XML(res.body) + self.assertEqual(root.tag.split('}')[1], "version") + self.assertEqual(root.tag.split('}')[0].strip('{'), + "http://docs.openstack.org/common/api/v1.0") + + children = list(root) + media_types = children[0] + media_type_nodes = list(media_types) + links = (children[1], children[2], children[3]) + + self.assertEqual(media_types.tag.split('}')[1], 'media-types') + for media_node in media_type_nodes: + self.assertEqual(media_node.tag.split('}')[1], 'media-type') + + expected = """ + serializer = versions.VersionsXMLSerializer() + response = serializer.detail(version_data) - - - - + root = xml.etree.ElementTree.XML(response) + self.assertEqual(root.tag.split('}')[1], "version") + self.assertEqual(root.tag.split('}')[0].strip('{'), + "http://docs.openstack.org/common/api/v1.0") - + children = list(root) + media_types = children[0] + media_type_nodes = list(media_types) + links = (children[1], children[2], children[3]) - + self.assertEqual(media_types.tag.split('}')[1], 'media-types') + for i, media_node in enumerate(media_type_nodes): + self.assertEqual(media_node.tag.split('}')[1], 'media-type') + for key, val in version_data['version']['media-types'][i].items(): + self.assertEqual(val, media_node.get(key)) - - """.replace(" ", "").replace("\n", "") + for i, link in enumerate(links): + self.assertEqual(link.tag.split('}')[0].strip('{'), + 'http://www.w3.org/2005/Atom') + self.assertEqual(link.tag.split('}')[1], 'link') + for key, val in version_data['version']['links'][i].items(): + self.assertEqual(val, link.get(key)) - serializer = versions.VersionsXMLSerializer() - response = serializer.detail(version_data) - response = response.replace(" ", "").replace("\n", "") - self.assertEqual(expected, response) def test_versions_list_atom_serializer(self): versions_data = { @@ -563,6 +575,51 @@ class VersionsTest(test.TestCase): response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) + root = xml.etree.ElementTree.XML(response) + self.assertEqual(root.tag.split('}')[1], "feed") + self.assertEqual(root.tag.split('}')[0].strip('{'), + "http://www.w3.org/2005/Atom") + + children = list(root) + title = children[0] + updated = children[1] + id = children[2] + author = children[3] + link = children[4] + entry = children[5] + + self.assertEqual(title.tag.split('}')[1], 'title') + self.assertEqual(title.text, 'Available API Versions') + self.assertEqual(updated.tag.split('}')[1], 'updated') + self.assertEqual(updated.text, '2011-07-20T11:40:00Z') + self.assertEqual(id.tag.split('}')[1], 'id') + self.assertEqual(id.text, 'http://test/') + + self.assertEqual(author.tag.split('}')[1], 'author') + author_name = list(author)[0] + author_uri = list(author)[1] + self.assertEqual(author_name.tag.split('}')[1], 'name') + self.assertEqual(author_name.text, 'Rackspace') + self.assertEqual(author_uri.tag.split('}')[1], 'uri') + self.assertEqual(author_uri.text, 'http://www.rackspace.com/') + + self.assertEqual(link.get('href'), 'http://test/') + self.assertEqual(link.get('rel'), 'self') + + self.assertEqual(entry.tag.split('}')[1], 'entry') + entry_children = list(entry) + entry_id = entry_children[0] + entry_title = entry_children[1] + entry_updated = entry_children[1] + + + + #self.assertEqual(media_types.tag.split('}')[1], 'media-types') + #for i, media_node in enumerate(media_type_nodes): + #self.assertEqual(media_node.tag.split('}')[1], 'media-type') + #for key, val in version_data['version']['media-types'][i].items(): + #self.assertEqual(val, media_node.get(key)) + def test_version_detail_atom_serializer(self): #TODO versions_data = { -- cgit From 696dc56b74a08d224beccdfd644536ec4217321d Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:15:44 -0400 Subject: updated atom tests --- nova/api/openstack/versions.py | 14 +++- nova/tests/api/openstack/test_versions.py | 111 +++++++++++++++--------------- 2 files changed, 65 insertions(+), 60 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index c250dac8c..03b99f342 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -115,7 +115,7 @@ class VersionV10(object): return { "version" : { "id": "v1.0", - "status": "CURRENT", + "status": "DEPRECATED", "updated": "2011-01-21T11:33:21Z", "links": [ { @@ -415,7 +415,15 @@ def create_resource(version='1.0'): 'application/xml': VersionsXMLSerializer(), 'application/atom+xml': VersionsAtomSerializer(), } - serializer = wsgi.ResponseSerializer(body_serializers) - return wsgi.Resource(controller, serializer=serializer) + supported_content_types = ('application/json', + 'application/xml', + 'application/atom+xml') + deserializer = wsgi.RequestDeserializer( + supported_content_types=supported_content_types) + + + + return wsgi.Resource(controller, serializer=serializer, + deserializer=deserializer) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index c48f397a1..88fe71041 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -271,75 +271,73 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, actual) def test_get_version_1_0_detail_atom(self): - #TODO req = webob.Request.blank('/v1.0/') - req.accept = "application/xml" + req.accept = "application/atom+xml" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) - self.assertEqual(res.content_type, "application/xml") + self.assertEqual("application/atom+xml", res.content_type) expected = """ - - - - - - - - - - - - - """.replace(" ", "").replace("\n", "") + + About This Version + 2011-01-21T11:33:21Z + http://servers.api.openstack.org/v1.0/ + + Rackspace + http://www.rackspace.com/ + + + + http://servers.api.openstack.org/v1.0/ + Version v1.0 + 2011-01-21T11:33:21Z + + + + + Version v1.0 DEPRECATED (2011-01-21T11:33:21Z) + + + """.replace(" ", "").replace("\n", "") actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) def test_get_version_1_1_detail_atom(self): - #TODO req = webob.Request.blank('/v1.1/') - req.accept = "application/xml" + req.accept = "application/atom+xml" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) - self.assertEqual(res.content_type, "application/xml") + self.assertEqual("application/atom+xml", res.content_type) expected = """ - - - - - - - - - - - - - """.replace(" ", "").replace("\n", "") + + About This Version + 2011-01-21T11:33:21Z + http://servers.api.openstack.org/v1.1/ + + Rackspace + http://www.rackspace.com/ + + + + http://servers.api.openstack.org/v1.1/ + Version v1.1 + 2011-01-21T11:33:21Z + + + + + Version v1.1 CURRENT (2011-01-21T11:33:21Z) + + + """.replace(" ", "").replace("\n", "") actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -621,7 +619,6 @@ class VersionsTest(test.TestCase): #self.assertEqual(val, media_node.get(key)) def test_version_detail_atom_serializer(self): - #TODO versions_data = { "version" : { "id": "v1.1", -- cgit From cdcc860cd5d513638c9d85b692f4b46b5e2832ef Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:18:08 -0400 Subject: fixed detail xml and json tests that got broken --- nova/tests/api/openstack/test_versions.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 88fe71041..448a69c07 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -80,7 +80,7 @@ class VersionsTest(test.TestCase): expected = { "version" : { "id" : "v1.0", - "status" : "CURRENT", + "status" : "DEPRECATED", "updated" : "2011-01-21T11:33:21Z", "links": [ { @@ -184,7 +184,7 @@ class VersionsTest(test.TestCase): expected = """ - @@ -609,6 +609,9 @@ class VersionsTest(test.TestCase): entry_id = entry_children[0] entry_title = entry_children[1] entry_updated = entry_children[1] + entry_link = entry_children[1] + entry_content = entry_children[1] + self.assertEqual(entry_id.text, "http://test/2.9.8") -- cgit From bde063a98dad2ce75be1016b39a2c3f08759d4f6 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:30:58 -0400 Subject: got rid of string comparisons in serializer tests --- nova/api/openstack/versions.py | 9 +++++ nova/tests/api/openstack/test_versions.py | 67 ++++++++----------------------- 2 files changed, 26 insertions(+), 50 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 03b99f342..40c187607 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -205,6 +205,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): # in the base class (XMLDictSerializer), which I plan to do in # another branch def to_xml_string(self, node, has_atom=False): + print "TOXML" self._add_xmlns(node, has_atom) return node.toxml(encoding='UTF-8') @@ -273,6 +274,14 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): class VersionsAtomSerializer(wsgi.XMLDictSerializer): + #TODO(wwolf): this is temporary until we get rid of toprettyxml + # in the base class (XMLDictSerializer), which I plan to do in + # another branch + def to_xml_string(self, node, has_atom=False): + print "TOXML" + self._add_xmlns(node, has_atom) + return node.toxml(encoding='UTF-8') + def __init__(self, metadata=None, xmlns=None): self.metadata = metadata or {} if not xmlns: diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 448a69c07..b8c985e4d 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -531,47 +531,9 @@ class VersionsTest(test.TestCase): ] } - expected = """ - - - Available API Versions - - - 2011-07-20T11:40:00Z - - - http://test/ - - - - Rackspace - - - http://www.rackspace.com/ - - - - - - http://test/2.9.8 - - - Version 2.9.8 - - - 2011-07-20T11:40:00Z - - - - Version 2.9.8 CURRENT (2011-07-20T11:40:00Z) - - - """.replace(" ", "").replace("\n", "") - serializer = versions.VersionsAtomSerializer() response = serializer.index(versions_data) - response = response.replace(" ", "").replace("\n", "") - self.assertEqual(expected, response) + print response root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "feed") @@ -608,18 +570,23 @@ class VersionsTest(test.TestCase): entry_children = list(entry) entry_id = entry_children[0] entry_title = entry_children[1] - entry_updated = entry_children[1] - entry_link = entry_children[1] - entry_content = entry_children[1] + entry_updated = entry_children[2] + entry_link = entry_children[3] + entry_content = entry_children[4] + self.assertEqual(entry_id.tag.split('}')[1], "id") self.assertEqual(entry_id.text, "http://test/2.9.8") - - - - #self.assertEqual(media_types.tag.split('}')[1], 'media-types') - #for i, media_node in enumerate(media_type_nodes): - #self.assertEqual(media_node.tag.split('}')[1], 'media-type') - #for key, val in version_data['version']['media-types'][i].items(): - #self.assertEqual(val, media_node.get(key)) + self.assertEqual(entry_title.tag.split('}')[1], "title") + self.assertEqual(entry_title.get('type'), "text") + self.assertEqual(entry_title.text, "Version 2.9.8") + self.assertEqual(entry_updated.tag.split('}')[1], "updated") + self.assertEqual(entry_updated.text, "2011-07-20T11:40:00Z") + self.assertEqual(entry_link.tag.split('}')[1], "link") + self.assertEqual(entry_link.get('href'), "http://test/2.9.8") + self.assertEqual(entry_link.get('rel'), "self") + self.assertEqual(entry_content.tag.split('}')[1], "content") + self.assertEqual(entry_content.get('type'), "text") + self.assertEqual(entry_content.text, + "Version 2.9.8 CURRENT (2011-07-20T11:40:00Z)") def test_version_detail_atom_serializer(self): versions_data = { -- cgit From 26f980c955e357df3685bcccda005a3008f86afb Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:31:16 -0400 Subject: got rid of some prints --- nova/api/openstack/versions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 40c187607..f389933b9 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -205,7 +205,6 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): # in the base class (XMLDictSerializer), which I plan to do in # another branch def to_xml_string(self, node, has_atom=False): - print "TOXML" self._add_xmlns(node, has_atom) return node.toxml(encoding='UTF-8') @@ -278,7 +277,6 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): # in the base class (XMLDictSerializer), which I plan to do in # another branch def to_xml_string(self, node, has_atom=False): - print "TOXML" self._add_xmlns(node, has_atom) return node.toxml(encoding='UTF-8') -- cgit From d3e557ae0d49ea8d4a1cd50abbada6e8c1c4a7fe Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:34:19 -0400 Subject: atom test updates --- nova/tests/api/openstack/test_versions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index b8c985e4d..59dc9fb92 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -548,6 +548,7 @@ class VersionsTest(test.TestCase): link = children[4] entry = children[5] + self.assertEqual(root.tag.split('}')[1], 'feed') self.assertEqual(title.tag.split('}')[1], 'title') self.assertEqual(title.text, 'Available API Versions') self.assertEqual(updated.tag.split('}')[1], 'updated') -- cgit From 3b6208f44c079323efa290dfeb68a4afbdfb3349 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:43:57 -0400 Subject: got rid of more xml string comparisons --- nova/tests/api/openstack/test_versions.py | 90 ++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 59dc9fb92..992efbf1c 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -548,7 +548,6 @@ class VersionsTest(test.TestCase): link = children[4] entry = children[5] - self.assertEqual(root.tag.split('}')[1], 'feed') self.assertEqual(title.tag.split('}')[1], 'title') self.assertEqual(title.text, 'Available API Versions') self.assertEqual(updated.tag.split('}')[1], 'updated') @@ -626,34 +625,65 @@ class VersionsTest(test.TestCase): }, } - expected = """ - - About This Version - 2011-01-21T11:33:21Z - http://servers.api.openstack.org/v1.1/ - - Rackspace - http://www.rackspace.com/ - - - - http://servers.api.openstack.org/v1.1/ - Version v1.1 - 2011-01-21T11:33:21Z - - - - - Version v1.1 CURRENT (2011-01-21T11:33:21Z) - - - """.replace(" ", "").replace("\n", "") - serializer = versions.VersionsAtomSerializer() response = serializer.detail(versions_data) - response = response.replace(" ", "").replace("\n", "") - self.assertEqual(expected, response) + + root = xml.etree.ElementTree.XML(response) + self.assertEqual(root.tag.split('}')[1], "feed") + self.assertEqual(root.tag.split('}')[0].strip('{'), + "http://www.w3.org/2005/Atom") + + children = list(root) + title = children[0] + updated = children[1] + id = children[2] + author = children[3] + link = children[4] + entry = children[5] + + self.assertEqual(root.tag.split('}')[1], 'feed') + self.assertEqual(title.tag.split('}')[1], 'title') + self.assertEqual(title.text, 'About This Version') + self.assertEqual(updated.tag.split('}')[1], 'updated') + self.assertEqual(updated.text, '2011-01-21T11:33:21Z') + self.assertEqual(id.tag.split('}')[1], 'id') + self.assertEqual(id.text, 'http://servers.api.openstack.org/v1.1/') + + self.assertEqual(author.tag.split('}')[1], 'author') + author_name = list(author)[0] + author_uri = list(author)[1] + self.assertEqual(author_name.tag.split('}')[1], 'name') + self.assertEqual(author_name.text, 'Rackspace') + self.assertEqual(author_uri.tag.split('}')[1], 'uri') + self.assertEqual(author_uri.text, 'http://www.rackspace.com/') + + self.assertEqual(link.get('href'), + 'http://servers.api.openstack.org/v1.1/') + self.assertEqual(link.get('rel'), 'self') + + self.assertEqual(entry.tag.split('}')[1], 'entry') + entry_children = list(entry) + entry_id = entry_children[0] + entry_title = entry_children[1] + entry_updated = entry_children[2] + entry_links = (entry_children[3], entry_children[4], entry_children[5]) + entry_content = entry_children[6] + + self.assertEqual(entry_id.tag.split('}')[1], "id") + self.assertEqual(entry_id.text, + "http://servers.api.openstack.org/v1.1/") + self.assertEqual(entry_title.tag.split('}')[1], "title") + self.assertEqual(entry_title.get('type'), "text") + self.assertEqual(entry_title.text, "Version v1.1") + self.assertEqual(entry_updated.tag.split('}')[1], "updated") + self.assertEqual(entry_updated.text, "2011-01-21T11:33:21Z") + + for i, link in enumerate(versions_data["version"]["links"]): + self.assertEqual(entry_links[i].tag.split('}')[1], "link") + for key, val in versions_data["version"]["links"][i].items(): + self.assertEqual(entry_links[i].get(key), val) + + self.assertEqual(entry_content.tag.split('}')[1], "content") + self.assertEqual(entry_content.get('type'), "text") + self.assertEqual(entry_content.text, + "Version v1.1 CURRENT (2011-01-21T11:33:21Z)") -- cgit From 58eef7695eb5539f75e358b2f55b50063551a44d Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 11:44:19 -0400 Subject: got rid of print --- nova/tests/api/openstack/test_versions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 992efbf1c..d1ec0b84a 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -533,7 +533,6 @@ class VersionsTest(test.TestCase): serializer = versions.VersionsAtomSerializer() response = serializer.index(versions_data) - print response root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "feed") -- cgit From b18754473785611112ae54523677da83dff24075 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Tue, 26 Jul 2011 20:58:33 +0000 Subject: First pass at converting this stuff--pass context down into vmops. Still need to fix unit tests and actually use auth_token from the context... --- nova/compute/manager.py | 9 +++++---- nova/virt/xenapi/vm_utils.py | 22 +++++++++++----------- nova/virt/xenapi/vmops.py | 29 +++++++++++++++-------------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 31627fe3b..667d231ae 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -326,7 +326,7 @@ class ComputeManager(manager.SchedulerDependentManager): self._update_state(context, instance_id, power_state.BUILDING) try: - self.driver.spawn(instance, network_info, bd_mapping) + self.driver.spawn(context, instance, network_info, bd_mapping) except Exception as ex: # pylint: disable=W0702 msg = _("Instance '%(instance_id)s' failed to spawn. Is " "virtualization enabled in the BIOS? Details: " @@ -430,7 +430,7 @@ class ComputeManager(manager.SchedulerDependentManager): image_ref = kwargs.get('image_ref') instance_ref.image_ref = image_ref instance_ref.injected_files = kwargs.get('injected_files', []) - self.driver.spawn(instance_ref, network_info) + self.driver.spawn(context, instance_ref, network_info) self._update_image_ref(context, instance_id, image_ref) self._update_launched_at(context, instance_id) @@ -498,7 +498,7 @@ class ComputeManager(manager.SchedulerDependentManager): 'instance: %(instance_id)s (state: %(state)s ' 'expected: %(running)s)') % locals()) - self.driver.snapshot(instance_ref, image_id) + self.driver.snapshot(context, instance_ref, image_id) if image_type == 'snapshot': if rotation: @@ -855,7 +855,8 @@ class ComputeManager(manager.SchedulerDependentManager): instance_ref = self.db.instance_get_by_uuid(context, instance_ref.uuid) network_info = self._get_instance_nw_info(context, instance_ref) - self.driver.finish_resize(instance_ref, disk_info, network_info) + self.driver.finish_resize(context, instance_ref, disk_info, + network_info) self.db.migration_update(context, migration_id, {'status': 'finished', }) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 62863c6d8..aa0e4c2df 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -359,7 +359,7 @@ class VMHelper(HelperBase): return os.path.join(FLAGS.xenapi_sr_base_path, sr_uuid) @classmethod - def upload_image(cls, session, instance, vdi_uuids, image_id): + def upload_image(cls, context, session, instance, vdi_uuids, image_id): """ Requests that the Glance plugin bundle the specified VDIs and push them into Glance using the specified human-friendly name. """ @@ -384,7 +384,7 @@ class VMHelper(HelperBase): session.wait_for_task(task, instance.id) @classmethod - def fetch_image(cls, session, instance_id, image, user, project, + def fetch_image(cls, context, session, instance_id, image, user, project, image_type): """ image_type is interpreted as an ImageType instance @@ -399,16 +399,16 @@ class VMHelper(HelperBase): access = AuthManager().get_access_key(user, project) if FLAGS.xenapi_image_service == 'glance': - return cls._fetch_image_glance(session, instance_id, image, - access, image_type) + return cls._fetch_image_glance(context, session, instance_id, + image, access, image_type) else: return cls._fetch_image_objectstore(session, instance_id, image, access, user.secret, image_type) @classmethod - def _fetch_image_glance_vhd(cls, session, instance_id, image, access, - image_type): + def _fetch_image_glance_vhd(cls, context, session, instance_id, image, + access, image_type): """Tell glance to download an image and put the VHDs into the SR Returns: A list of dictionaries that describe VDIs @@ -455,8 +455,8 @@ class VMHelper(HelperBase): return vdis @classmethod - def _fetch_image_glance_disk(cls, session, instance_id, image, access, - image_type): + def _fetch_image_glance_disk(cls, context, session, instance_id, image, + access, image_type): """Fetch the image from Glance NOTE: @@ -589,7 +589,7 @@ class VMHelper(HelperBase): return image_type @classmethod - def _fetch_image_glance(cls, session, instance_id, image, access, + def _fetch_image_glance(cls, context, session, instance_id, image, access, image_type): """Fetch image from glance based on image type. @@ -597,10 +597,10 @@ class VMHelper(HelperBase): A list of dictionaries that describe VDIs, otherwise """ if image_type == ImageType.DISK_VHD: - return cls._fetch_image_glance_vhd( + return cls._fetch_image_glance_vhd(context, session, instance_id, image, access, image_type) else: - return cls._fetch_image_glance_disk( + return cls._fetch_image_glance_disk(context, session, instance_id, image, access, image_type) @classmethod diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 0473abb97..1c6604836 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -114,10 +114,10 @@ class VMOps(object): vm_ref = VMHelper.lookup(self._session, instance.name) self._start(instance, vm_ref) - def finish_resize(self, instance, disk_info, network_info): + def finish_resize(self, context, instance, disk_info, network_info): vdi_uuid = self.link_disks(instance, disk_info['base_copy'], disk_info['cow']) - vm_ref = self._create_vm(instance, + vm_ref = self._create_vm(context, instance, [dict(vdi_type='os', vdi_uuid=vdi_uuid)], network_info) self.resize_instance(instance, vdi_uuid) @@ -133,20 +133,20 @@ class VMOps(object): LOG.debug(_("Starting instance %s"), instance.name) self._session.call_xenapi('VM.start', vm_ref, False, False) - def _create_disks(self, instance): + def _create_disks(self, context, instance): user = AuthManager().get_user(instance.user_id) project = AuthManager().get_project(instance.project_id) disk_image_type = VMHelper.determine_disk_image_type(instance) - vdis = VMHelper.fetch_image(self._session, + vdis = VMHelper.fetch_image(context, self._session, instance.id, instance.image_ref, user, project, disk_image_type) return vdis - def spawn(self, instance, network_info): + def spawn(self, context, instance, network_info): vdis = None try: - vdis = self._create_disks(instance) - vm_ref = self._create_vm(instance, vdis, network_info) + vdis = self._create_disks(context, instance) + vm_ref = self._create_vm(context, instance, vdis, network_info) self._spawn(instance, vm_ref) except (self.XenAPI.Failure, OSError, IOError) as spawn_error: LOG.exception(_("instance %s: Failed to spawn"), @@ -160,7 +160,7 @@ class VMOps(object): """Spawn a rescue instance.""" self.spawn(instance) - def _create_vm(self, instance, vdis, network_info): + def _create_vm(self, context, instance, vdis, network_info): """Create VM instance.""" instance_name = instance.name vm_ref = VMHelper.lookup(self._session, instance_name) @@ -184,12 +184,12 @@ class VMOps(object): ramdisk = None try: if instance.kernel_id: - kernel = VMHelper.fetch_image(self._session, instance.id, - instance.kernel_id, user, project, + kernel = VMHelper.fetch_image(context, self._session, + instance.id, instance.kernel_id, user, project, ImageType.KERNEL)[0] if instance.ramdisk_id: - ramdisk = VMHelper.fetch_image(self._session, instance.id, - instance.ramdisk_id, user, project, + ramdisk = VMHelper.fetch_image(context, self._session, + instance.id, instance.ramdisk_id, user, project, ImageType.RAMDISK)[0] # Create the VM ref and attach the first disk first_vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', @@ -440,9 +440,10 @@ class VMOps(object): vm, "start") - def snapshot(self, instance, image_id): + def snapshot(self, context, instance, image_id): """Create snapshot from a running VM instance. + :param context: request context :param instance: instance to be snapshotted :param image_id: id of image to upload to @@ -467,7 +468,7 @@ class VMOps(object): try: template_vm_ref, template_vdi_uuids = self._get_snapshot(instance) # call plugin to ship snapshot off to glance - VMHelper.upload_image( + VMHelper.upload_image(context, self._session, instance, template_vdi_uuids, image_id) finally: if template_vm_ref: -- cgit From e14754bbdbacaf6943c4061e3488f2580acd26ad Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 17:51:46 -0400 Subject: initial working 300 multiple choice stuff --- nova/api/openstack/__init__.py | 2 +- nova/api/openstack/versions.py | 191 +++++++++++++++++------------- nova/api/openstack/views/versions.py | 8 ++ nova/tests/api/openstack/test_versions.py | 59 ++++++++- 4 files changed, 174 insertions(+), 86 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c10937bd6..0dfad0ef6 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -118,7 +118,7 @@ class APIRouter(base_wsgi.Router): mapper.connect("versions", "/", controller=versions.create_resource(version), - action="detail") + action='show') mapper.resource("console", "consoles", controller=consoles.create_resource(), diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index f389933b9..4b567957d 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -25,6 +25,80 @@ from nova.api.openstack import wsgi ATOM_XMLNS = "http://www.w3.org/2005/Atom" +VERSIONS = { + "v1.0": { + "version" : { + "id": "v1.0", + "status": "DEPRECATED", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.0/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.0+json" + } + ], + }, + }, + "v1.1": { + "version" : { + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.1/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.1+json" + } + ], + }, + }, +} + + class Versions(wsgi.Resource): @@ -43,11 +117,15 @@ class Versions(wsgi.Resource): } } + headers_serializer = VersionsHeadersSerializer() + body_serializers = { 'application/atom+xml': VersionsAtomSerializer(metadata=metadata), 'application/xml': VersionsXMLSerializer(metadata=metadata), } - serializer = wsgi.ResponseSerializer(body_serializers) + serializer = wsgi.ResponseSerializer( + body_serializers=body_serializers, + headers_serializer=headers_serializer) supported_content_types = ('application/json', 'application/xml', @@ -93,100 +171,41 @@ class Versions(wsgi.Resource): { "id": "v1.1", "status": "CURRENT", - #TODO(wwolf) get correct value for these - "updated": "2011-07-18T11:30:00Z", + "links": [ + { + "rel": "self", + } + ], + "media-types": VERSIONS['v1.1']['version']['media-types'], }, { "id": "v1.0", "status": "DEPRECATED", - #TODO(wwolf) get correct value for these - "updated": "2010-10-09T11:30:00Z", + "links": [ + { + "rel": "self", + } + ], + "media-types": VERSIONS['v1.0']['version']['media-types'], }, ] builder = nova.api.openstack.views.versions.get_view_builder(request) - versions = [builder.build(version) for version in version_objs] - return dict(versions=versions) + choices = [ + builder.build_choices(version, request) + for version in version_objs] + + return dict(choices=choices) class VersionV10(object): - def detail(self, req): - #TODO - return { - "version" : { - "id": "v1.0", - "status": "DEPRECATED", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.0/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" - }, - ], - "media-types": [ - { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.0+xml" - }, - { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.0+json" - } - ], - }, - } + def show(self, req): + return VERSIONS['v1.0'] class VersionV11(object): - def detail(self, req): - return { - "version" : { - "id": "v1.1", - "status": "CURRENT", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" - }, - ], - "media-types": [ - { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.1+xml" - }, - { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.1+json" - } - ], - }, - } - + def show(self, req): + return VERSIONS['v1.1'] class VersionsRequestDeserializer(wsgi.RequestDeserializer): def get_action_args(self, request_environment): @@ -259,7 +278,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) - def detail(self,data): + def show(self,data): self._xml_doc = minidom.Document() node = self._create_version_node(data['version'], True) @@ -404,7 +423,7 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) - def detail(self, data): + def show(self, data): self._xml_doc = minidom.Document() node = self._xml_doc.createElementNS(self.xmlns, 'feed') self._create_detail_meta(node, data['version']) @@ -412,6 +431,12 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) + +class VersionsHeadersSerializer(wsgi.ResponseHeadersSerializer): + def multi(self, response, data): + response.status_int = 300 + + def create_resource(version='1.0'): controller = { '1.0': VersionV10, diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index 9fa8f49dc..97e35c983 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -31,6 +31,11 @@ class ViewBuilder(object): """ self.base_url = base_url + def build_choices(self, version_data, request): + version_data['links'][0]['href'] = self._build_versioned_link(request, + version_data['id']) + return version_data + def build(self, version_data): """Generic method used to generate a version entity.""" version = { @@ -42,6 +47,9 @@ class ViewBuilder(object): return version + def _build_versioned_link(self, req, version): + return '%s://%s/%s%s' % (req.scheme, req.host, version, req.path) + def _build_links(self, version_data): """Generate a container of links that refer to the provided version.""" href = self.generate_href(version_data["id"]) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index d1ec0b84a..f33ef5e6a 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -384,6 +384,61 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, actual) + def test_multi_choice_servers_list(self): + req = webob.Request.blank('/servers/2') + req.accept = "application/json" + res = req.get_response(fakes.wsgi_app()) + print res.body + self.assertEqual(res.status_int, 300) + self.assertEqual(res.content_type, "application/json") + + expected = { + "choices": [ + { + "id": "v1.1", + "status": "CURRENT", + "links": [ + { + "href": "http://localhost:80/v1.1/servers/2", + "rel": "self", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" + }, + ], + }, + { + "id": "v1.0", + "status": "DEPRECATED", + "links": [ + { + "href": "http://localhost:80/v1.0/servers/2", + "rel": "self", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" + }, + ], + }, + ],} + + self.assertDictMatch(expected, json.loads(res.body)) + + def test_view_builder(self): base_url = "http://example.org/" @@ -488,7 +543,7 @@ class VersionsTest(test.TestCase): } serializer = versions.VersionsXMLSerializer() - response = serializer.detail(version_data) + response = serializer.show(version_data) root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "version") @@ -625,7 +680,7 @@ class VersionsTest(test.TestCase): } serializer = versions.VersionsAtomSerializer() - response = serializer.detail(versions_data) + response = serializer.show(versions_data) root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "feed") -- cgit From 6dbd7583f4f1ca4be59e163c4c568423a91cd29e Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 18:10:36 -0400 Subject: pep8 fixes --- nova/api/openstack/__init__.py | 4 +-- nova/api/openstack/versions.py | 31 +++++++++--------- nova/tests/api/openstack/test_versions.py | 52 +++++++++++++++---------------- 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 0dfad0ef6..96a2f20e0 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -116,8 +116,8 @@ class APIRouter(base_wsgi.Router): 'select': 'POST', 'boot': 'POST'}) - mapper.connect("versions", "/", - controller=versions.create_resource(version), + mapper.connect("versions", "/", + controller=versions.create_resource(version), action='show') mapper.resource("console", "consoles", diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 4b567957d..58c767d5c 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -25,12 +25,12 @@ from nova.api.openstack import wsgi ATOM_XMLNS = "http://www.w3.org/2005/Atom" -VERSIONS = { +VERSIONS = { "v1.0": { - "version" : { + "version" : { "id": "v1.0", "status": "DEPRECATED", - "updated": "2011-01-21T11:33:21Z", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -41,7 +41,7 @@ VERSIONS = { "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" "servers/api/v1.0/cs-devguide-20110125.pdf" - }, + }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", @@ -62,7 +62,7 @@ VERSIONS = { }, }, "v1.1": { - "version" : { + "version" : { "id": "v1.1", "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", @@ -76,7 +76,7 @@ VERSIONS = { "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" "servers/api/v1.1/cs-devguide-20110125.pdf" - }, + }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", @@ -99,8 +99,6 @@ VERSIONS = { } - - class Versions(wsgi.Resource): @classmethod def factory(cls, global_config, **local_config): @@ -192,7 +190,7 @@ class Versions(wsgi.Resource): builder = nova.api.openstack.views.versions.get_view_builder(request) choices = [ - builder.build_choices(version, request) + builder.build_choices(version, request) for version in version_objs] return dict(choices=choices) @@ -207,6 +205,7 @@ class VersionV11(object): def show(self, req): return VERSIONS['v1.1'] + class VersionsRequestDeserializer(wsgi.RequestDeserializer): def get_action_args(self, request_environment): """Parse dictionary created by routes library.""" @@ -220,8 +219,8 @@ class VersionsRequestDeserializer(wsgi.RequestDeserializer): class VersionsXMLSerializer(wsgi.XMLDictSerializer): - #TODO(wwolf): this is temporary until we get rid of toprettyxml - # in the base class (XMLDictSerializer), which I plan to do in + #TODO(wwolf): this is temporary until we get rid of toprettyxml + # in the base class (XMLDictSerializer), which I plan to do in # another branch def to_xml_string(self, node, has_atom=False): self._add_xmlns(node, has_atom) @@ -244,7 +243,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): base.appendChild(node) return base - + def _create_version_node(self, version, create_ns=False): version_node = self._xml_doc.createElement('version') if create_ns: @@ -278,7 +277,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) - def show(self,data): + def show(self, data): self._xml_doc = minidom.Document() node = self._create_version_node(data['version'], True) @@ -292,8 +291,8 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): class VersionsAtomSerializer(wsgi.XMLDictSerializer): - #TODO(wwolf): this is temporary until we get rid of toprettyxml - # in the base class (XMLDictSerializer), which I plan to do in + #TODO(wwolf): this is temporary until we get rid of toprettyxml + # in the base class (XMLDictSerializer), which I plan to do in # another branch def to_xml_string(self, node, has_atom=False): self._add_xmlns(node, has_atom) @@ -455,7 +454,5 @@ def create_resource(version='1.0'): deserializer = wsgi.RequestDeserializer( supported_content_types=supported_content_types) - - return wsgi.Resource(controller, serializer=serializer, deserializer=deserializer) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index f33ef5e6a..587b085c3 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -35,7 +35,6 @@ class VersionsTest(test.TestCase): self.stubs = stubout.StubOutForTesting() fakes.stub_out_auth(self.stubs) - def tearDown(self): super(VersionsTest, self).tearDown() @@ -182,12 +181,11 @@ class VersionsTest(test.TestCase): for media_node in media_type_nodes: self.assertEqual(media_node.tag.split('}')[1], 'media-type') - expected = """ - + + rel="describedby" + type="application/vnd.sun.wadl+xml"/> """.replace(" ", "").replace("\n", "") actual = res.body.replace(" ", "").replace("\n", "") @@ -220,10 +218,10 @@ class VersionsTest(test.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res.content_type, "application/xml") expected = """ - + + rel="describedby" + type="application/vnd.sun.wadl+xml"/> """.replace(" ", "").replace("\n", "") actual = res.body.replace(" ", "").replace("\n", "") @@ -290,7 +288,8 @@ class VersionsTest(test.TestCase): http://servers.api.openstack.org/v1.0/ Version v1.0 2011-01-21T11:33:21Z - + @@ -326,7 +325,8 @@ class VersionsTest(test.TestCase): http://servers.api.openstack.org/v1.1/ Version v1.1 2011-01-21T11:33:21Z - + @@ -407,13 +407,13 @@ class VersionsTest(test.TestCase): { "base": "application/xml", "type": "application/vnd.openstack.compute-v1.1+xml" - }, + }, { "base": "application/json", "type": "application/vnd.openstack.compute-v1.1+json" }, ], - }, + }, { "id": "v1.0", "status": "DEPRECATED", @@ -432,13 +432,12 @@ class VersionsTest(test.TestCase): "base": "application/json", "type": "application/vnd.openstack.compute-v1.0+json" }, - ], + ], }, - ],} + ], } self.assertDictMatch(expected, json.loads(res.body)) - def test_view_builder(self): base_url = "http://example.org/" @@ -507,10 +506,10 @@ class VersionsTest(test.TestCase): def test_version_detail_xml_serializer(self): version_data = { - "version" : { + "version" : { "id": "v1.0", "status": "CURRENT", - "updated": "2011-01-21T11:33:21Z", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -521,7 +520,7 @@ class VersionsTest(test.TestCase): "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" "servers/api/v1.0/cs-devguide-20110125.pdf" - }, + }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", @@ -568,7 +567,6 @@ class VersionsTest(test.TestCase): for key, val in version_data['version']['links'][i].items(): self.assertEqual(val, link.get(key)) - def test_versions_list_atom_serializer(self): versions_data = { 'versions': [ @@ -644,7 +642,7 @@ class VersionsTest(test.TestCase): def test_version_detail_atom_serializer(self): versions_data = { - "version" : { + "version" : { "id": "v1.1", "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", @@ -658,7 +656,7 @@ class VersionsTest(test.TestCase): "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" "servers/api/v1.1/cs-devguide-20110125.pdf" - }, + }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", -- cgit From 15068c4038d93db77278ea3306d992b424168c24 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 18:16:28 -0400 Subject: added multi_choice test just to hit another resource --- nova/tests/api/openstack/test_versions.py | 56 +++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 587b085c3..d8d6cebe2 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -384,11 +384,63 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, actual) - def test_multi_choice_servers_list(self): + def test_multi_choice_image(self): + req = webob.Request.blank('/images/1') + req.accept = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 300) + self.assertEqual(res.content_type, "application/json") + + expected = { + "choices": [ + { + "id": "v1.1", + "status": "CURRENT", + "links": [ + { + "href": "http://localhost:80/v1.1/images/1", + "rel": "self", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" + }, + ], + }, + { + "id": "v1.0", + "status": "DEPRECATED", + "links": [ + { + "href": "http://localhost:80/v1.0/images/1", + "rel": "self", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" + }, + ], + }, + ], } + + self.assertDictMatch(expected, json.loads(res.body)) + + def test_multi_choice_server(self): req = webob.Request.blank('/servers/2') req.accept = "application/json" res = req.get_response(fakes.wsgi_app()) - print res.body self.assertEqual(res.status_int, 300) self.assertEqual(res.content_type, "application/json") -- cgit From c95ee1625a6a88afdb77d305077d1ee7eeaae854 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 26 Jul 2011 16:20:31 -0700 Subject: fix for lp816713: In instance creation, when nova-api is passed imageRefs generated by itself, strip the url down to an id so that default glance connection params are used --- nova/api/openstack/create_instance_helper.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index f8317565e..0e6c0a87c 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -87,6 +87,10 @@ class CreateInstanceHelper(object): key_data = key_pair['public_key'] image_href = self.controller._image_ref_from_req_data(body) + # If the image href was generated by nova api, strip image_href + # down to an id and use the default glance connection params + if image_href.startswith(req.application_url): + image_href = image_href.split('/').pop() try: image_service, image_id = nova.image.get_image_service(image_href) kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image( -- cgit From 74e3218d2b6045457019c4de518ca4a869e37807 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 09:11:41 -0400 Subject: multi choice XML responses with tests --- nova/api/openstack/versions.py | 15 ++++-- nova/tests/api/openstack/test_versions.py | 87 +++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 58c767d5c..9909d8d0d 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -25,6 +25,7 @@ from nova.api.openstack import wsgi ATOM_XMLNS = "http://www.w3.org/2005/Atom" +OS_XMLNS_BASE = "http://docs.openstack.org/common/api/" VERSIONS = { "v1.0": { "version" : { @@ -226,8 +227,10 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): self._add_xmlns(node, has_atom) return node.toxml(encoding='UTF-8') - def _versions_to_xml(self, versions): - root = self._xml_doc.createElement('versions') + def _versions_to_xml(self, versions, name="versions", xmlns=None): + root = self._xml_doc.createElement(name) + root.setAttribute("xmlns", "%sv1.0" % OS_XMLNS_BASE) + root.setAttribute("xmlns:atom", ATOM_XMLNS) for version in versions: root.appendChild(self._create_version_node(version)) @@ -247,14 +250,15 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _create_version_node(self, version, create_ns=False): version_node = self._xml_doc.createElement('version') if create_ns: - xmlns = "http://docs.openstack.org/common/api/%s" % version['id'] + xmlns = "%s%s" % (OS_XMLNS_BASE, version['id']) xmlns_atom = "http://www.w3.org/2005/Atom" version_node.setAttribute('xmlns', xmlns) version_node.setAttribute('xmlns:atom', xmlns_atom) version_node.setAttribute('id', version['id']) version_node.setAttribute('status', version['status']) - version_node.setAttribute('updated', version['updated']) + if 'updated' in version: + version_node.setAttribute('updated', version['updated']) if 'media-types' in version: media_types = self._create_media_types(version['media-types']) @@ -285,7 +289,8 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def multi(self, data): self._xml_doc = minidom.Document() - node = self._versions_to_xml(data['versions']) + node = self._versions_to_xml(data['choices'], 'choices', + xmlns="%sv1.0" % OS_XMLNS_BASE) return self.to_xml_string(node) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index d8d6cebe2..dce8e38f1 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -27,6 +27,9 @@ from nova.tests.api.openstack import fakes from nova.api.openstack import versions from nova.api.openstack import views +ATOM_XMLNS = versions.ATOM_XMLNS +OS_XMLNS_BASE = versions.OS_XMLNS_BASE + class VersionsTest(test.TestCase): def setUp(self): @@ -170,7 +173,7 @@ class VersionsTest(test.TestCase): root = xml.etree.ElementTree.XML(res.body) self.assertEqual(root.tag.split('}')[1], "version") self.assertEqual(root.tag.split('}')[0].strip('{'), - "http://docs.openstack.org/common/api/v1.0") + "%sv1.0" % OS_XMLNS_BASE) children = list(root) media_types = children[0] @@ -184,7 +187,7 @@ class VersionsTest(test.TestCase): expected = """ @@ -206,7 +209,7 @@ class VersionsTest(test.TestCase): api/v1.0/application.wadl" rel="describedby" type="application/vnd.sun.wadl+xml"/> - """.replace(" ", "").replace("\n", "") + """.replace(" ", "").replace("\n", "") % OS_XMLNS_BASE actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -220,7 +223,7 @@ class VersionsTest(test.TestCase): expected = """ @@ -242,7 +245,8 @@ class VersionsTest(test.TestCase): api/v1.1/application.wadl" rel="describedby" type="application/vnd.sun.wadl+xml"/> - """.replace(" ", "").replace("\n", "") + """.replace(" ", "").replace("\n", "") % OS_XMLNS_BASE + actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -254,7 +258,8 @@ class VersionsTest(test.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res.content_type, "application/xml") - expected = """ + expected = """ + @@ -262,7 +267,8 @@ class VersionsTest(test.TestCase): updated="2010-10-09T11:30:00Z"> - """.replace(" ", "").replace("\n", "") + """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, + ATOM_XMLNS) actual = res.body.replace(" ", "").replace("\n", "") @@ -437,6 +443,36 @@ class VersionsTest(test.TestCase): self.assertDictMatch(expected, json.loads(res.body)) + def test_multi_choice_image_xml(self): + req = webob.Request.blank('/images/1') + req.accept = "application/xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 300) + self.assertEqual(res.content_type, "application/xml") + + expected = """ + + + + + + + + + + + + + + + + """.replace(" ", "").replace("\n","") % (OS_XMLNS_BASE, + ATOM_XMLNS) + def test_multi_choice_server(self): req = webob.Request.blank('/servers/2') req.accept = "application/json" @@ -544,18 +580,51 @@ class VersionsTest(test.TestCase): } expected = """ - + - """.replace(" ", "").replace("\n", "") + """.replace(" ", "").replace("\n", "") % ( + OS_XMLNS_BASE,ATOM_XMLNS) serializer = versions.VersionsXMLSerializer() response = serializer.index(versions_data) response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) + def test_versions_multi_xml_serializer(self): + versions_data = { + 'choices': [ + { + "id": "2.7.1", + "updated": "2011-07-18T11:30:00Z", + "status": "DEPRECATED", + "links": [ + { + "rel": "self", + "href": "http://test/2.7.1/images", + }, + ], + }, + ] + } + + expected = """ + + + + + """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, + ATOM_XMLNS) + + serializer = versions.VersionsXMLSerializer() + response = serializer.multi(versions_data) + response = response.replace(" ", "").replace("\n", "") + self.assertEqual(expected, response) + + def test_version_detail_xml_serializer(self): version_data = { "version" : { -- cgit From 8389d214a917f1c4f2d8ddb471f94c6087ec9ea9 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 09:13:48 -0400 Subject: pep8 cleanup --- nova/tests/api/openstack/test_versions.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index dce8e38f1..b2fb0efb6 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -247,7 +247,6 @@ class VersionsTest(test.TestCase): type="application/vnd.sun.wadl+xml"/> """.replace(" ", "").replace("\n", "") % OS_XMLNS_BASE - actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -470,7 +469,7 @@ class VersionsTest(test.TestCase): - """.replace(" ", "").replace("\n","") % (OS_XMLNS_BASE, + """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, ATOM_XMLNS) def test_multi_choice_server(self): @@ -586,7 +585,7 @@ class VersionsTest(test.TestCase): """.replace(" ", "").replace("\n", "") % ( - OS_XMLNS_BASE,ATOM_XMLNS) + OS_XMLNS_BASE, ATOM_XMLNS) serializer = versions.VersionsXMLSerializer() response = serializer.index(versions_data) @@ -624,7 +623,6 @@ class VersionsTest(test.TestCase): response = response.replace(" ", "").replace("\n", "") self.assertEqual(expected, response) - def test_version_detail_xml_serializer(self): version_data = { "version" : { -- cgit From c5c3a5696d11320e7fe0bfbe942610e93fbd1ab4 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 09:30:15 -0400 Subject: updated serializer tests for multi choice --- nova/tests/api/openstack/test_versions.py | 71 +++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index b2fb0efb6..9460e1004 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -29,6 +29,7 @@ from nova.api.openstack import views ATOM_XMLNS = versions.ATOM_XMLNS OS_XMLNS_BASE = versions.OS_XMLNS_BASE +VERSIONS = versions.VERSIONS class VersionsTest(test.TestCase): @@ -578,19 +579,26 @@ class VersionsTest(test.TestCase): ] } - expected = """ - - - - - """.replace(" ", "").replace("\n", "") % ( - OS_XMLNS_BASE, ATOM_XMLNS) - serializer = versions.VersionsXMLSerializer() response = serializer.index(versions_data) - response = response.replace(" ", "").replace("\n", "") - self.assertEqual(expected, response) + + root = xml.etree.ElementTree.XML(response) + self.assertEqual(root.tag.split('}')[1], "versions") + self.assertEqual(root.tag.split('}')[0].strip('{'), + "%sv1.0" % OS_XMLNS_BASE) + version = list(root)[0] + self.assertEqual(version.tag.split('}')[1], "version") + self.assertEqual(version.get('id'), + versions_data['versions'][0]['id']) + self.assertEqual(version.get('status'), + versions_data['versions'][0]['status']) + + link = list(version)[0] + + self.assertEqual(link.tag.split('}')[1], "link") + self.assertEqual(link.tag.split('}')[0].strip('{'), ATOM_XMLNS) + for key, val in versions_data['versions'][0]['links'][0].items(): + self.assertEqual(link.get(key), val) def test_versions_multi_xml_serializer(self): versions_data = { @@ -599,6 +607,7 @@ class VersionsTest(test.TestCase): "id": "2.7.1", "updated": "2011-07-18T11:30:00Z", "status": "DEPRECATED", + "media-types": VERSIONS['v1.1']['version']['media-types'], "links": [ { "rel": "self", @@ -609,19 +618,37 @@ class VersionsTest(test.TestCase): ] } - expected = """ - - - - - """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, - ATOM_XMLNS) - serializer = versions.VersionsXMLSerializer() response = serializer.multi(versions_data) - response = response.replace(" ", "").replace("\n", "") - self.assertEqual(expected, response) + + root = xml.etree.ElementTree.XML(response) + self.assertEqual(root.tag.split('}')[1], "choices") + self.assertEqual(root.tag.split('}')[0].strip('{'), + "%sv1.0" % OS_XMLNS_BASE) + version = list(root)[0] + self.assertEqual(version.tag.split('}')[1], "version") + self.assertEqual(version.get('id'), versions_data['choices'][0]['id']) + self.assertEqual(version.get('status'), + versions_data['choices'][0]['status']) + + media_types = list(version)[0] + media_type_nodes = list(media_types) + self.assertEqual(media_types.tag.split('}')[1], "media-types") + + set_types = versions_data['choices'][0]['media-types'] + for i, type in enumerate(set_types): + node = media_type_nodes[i] + self.assertEqual(node.tag.split('}')[1], "media-type") + for key, val in set_types[i].items(): + self.assertEqual(node.get(key), val) + + link = list(version)[1] + + self.assertEqual(link.tag.split('}')[1], "link") + self.assertEqual(link.tag.split('}')[0].strip('{'), ATOM_XMLNS) + for key, val in versions_data['choices'][0]['links'][0].items(): + self.assertEqual(link.get(key), val) + def test_version_detail_xml_serializer(self): version_data = { -- cgit From 6dead0b1706f3b2279504437aca63a3291dc2347 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 12:06:12 -0400 Subject: pep8 --- nova/tests/api/openstack/test_versions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 9460e1004..cbc98a4b4 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -649,7 +649,6 @@ class VersionsTest(test.TestCase): for key, val in versions_data['choices'][0]['links'][0].items(): self.assertEqual(link.get(key), val) - def test_version_detail_xml_serializer(self): version_data = { "version" : { -- cgit From 5ca4d3a88f1dd758c4ab6133e26cf2f8b05a8339 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 12:50:52 -0400 Subject: pep8 --- nova/api/openstack/versions.py | 20 ++++---- nova/tests/api/openstack/test_versions.py | 84 +++++++++++++++---------------- run_tests.sh | 4 +- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 9909d8d0d..4d40274b3 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -28,7 +28,7 @@ ATOM_XMLNS = "http://www.w3.org/2005/Atom" OS_XMLNS_BASE = "http://docs.openstack.org/common/api/" VERSIONS = { "v1.0": { - "version" : { + "version": { "id": "v1.0", "status": "DEPRECATED", "updated": "2011-01-21T11:33:21Z", @@ -52,18 +52,18 @@ VERSIONS = { ], "media-types": [ { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.0+xml" + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" }, { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.0+json" + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" } ], }, }, "v1.1": { - "version" : { + "version": { "id": "v1.1", "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", @@ -87,12 +87,12 @@ VERSIONS = { ], "media-types": [ { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.1+xml" + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" }, { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.1+json" + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" } ], }, diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index cbc98a4b4..3f7867ff4 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -81,37 +81,37 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/json") version = json.loads(res.body) expected = { - "version" : { - "id" : "v1.0", - "status" : "DEPRECATED", - "updated" : "2011-01-21T11:33:21Z", + "version": { + "id": "v1.0", + "status": "DEPRECATED", + "updated": "2011-01-21T11:33:21Z", "links": [ { - "rel" : "self", - "href" : "http://servers.api.openstack.org/v1.0/" + "rel": "self", + "href": "http://servers.api.openstack.org/v1.0/" }, { - "rel" : "describedby", - "type" : "application/pdf", - "href" : "http://docs.rackspacecloud.com/" + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" "servers/api/v1.0/cs-devguide-20110125.pdf" }, { - "rel" : "describedby", - "type" : "application/vnd.sun.wadl+xml", - "href" : "http://docs.rackspacecloud.com/" + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" "servers/api/v1.0/application.wadl" } ], "media-types": [ { - "base" : "application/xml", - "type" : "application/" + "base": "application/xml", + "type": "application/" "vnd.openstack.compute-v1.0+xml" }, { - "base" : "application/json", - "type" : "application/" + "base": "application/json", + "type": "application/" "vnd.openstack.compute-v1.0+json" } ] @@ -127,37 +127,37 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/json") version = json.loads(res.body) expected = { - "version" : { - "id" : "v1.1", - "status" : "CURRENT", - "updated" : "2011-01-21T11:33:21Z", + "version": { + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", "links": [ { - "rel" : "self", - "href" : "http://servers.api.openstack.org/v1.1/" + "rel": "self", + "href": "http://servers.api.openstack.org/v1.1/" }, { - "rel" : "describedby", - "type" : "application/pdf", - "href" : "http://docs.rackspacecloud.com/" + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" "servers/api/v1.1/cs-devguide-20110125.pdf" }, { - "rel" : "describedby", - "type" : "application/vnd.sun.wadl+xml", - "href" : "http://docs.rackspacecloud.com/" + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" "servers/api/v1.1/application.wadl" } ], "media-types": [ { - "base" : "application/xml", - "type" : "application/" + "base": "application/xml", + "type": "application/" "vnd.openstack.compute-v1.1+xml" }, { - "base" : "application/json", - "type" : "application/" + "base": "application/json", + "type": "application/" "vnd.openstack.compute-v1.1+json" } ] @@ -651,7 +651,7 @@ class VersionsTest(test.TestCase): def test_version_detail_xml_serializer(self): version_data = { - "version" : { + "version": { "id": "v1.0", "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", @@ -675,12 +675,12 @@ class VersionsTest(test.TestCase): ], "media-types": [ { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.0+xml" + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" }, { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.0+json" + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" } ], }, @@ -787,7 +787,7 @@ class VersionsTest(test.TestCase): def test_version_detail_atom_serializer(self): versions_data = { - "version" : { + "version": { "id": "v1.1", "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", @@ -811,12 +811,12 @@ class VersionsTest(test.TestCase): ], "media-types": [ { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.1+xml" + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" }, { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.1+json" + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" } ], }, diff --git a/run_tests.sh b/run_tests.sh index 8f2b51757..e39ecd315 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -84,7 +84,9 @@ function run_pep8 { srcfiles+=" `find tools/*`" srcfiles+=" nova setup.py plugins/xenserver/xenapi/etc/xapi.d/plugins/glance" # Just run PEP8 in current environment - ${wrapper} pep8 --repeat --show-pep8 --show-source \ + #${wrapper} pep8 --repeat --show-pep8 --show-source \ + #--exclude=vcsversion.py ${srcfiles} + pep8 --repeat --show-pep8 --show-source \ --exclude=vcsversion.py ${srcfiles} } -- cgit From b847ed1cbac345bd2d7a8c252080656c8109c052 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Wed, 27 Jul 2011 17:16:46 +0000 Subject: Add context argument a lot more places and make unit tests work --- nova/tests/test_libvirt.py | 6 +++--- nova/tests/test_xenapi.py | 16 +++++++++------- nova/tests/xenapi/stubs.py | 4 ++-- nova/virt/driver.py | 7 ++++--- nova/virt/fake.py | 5 +++-- nova/virt/hyperv.py | 3 ++- nova/virt/libvirt/connection.py | 5 +++-- nova/virt/vmwareapi/vmops.py | 4 ++-- nova/virt/vmwareapi_conn.py | 9 +++++---- nova/virt/xenapi/vmops.py | 4 ++-- nova/virt/xenapi_conn.py | 13 +++++++------ 11 files changed, 42 insertions(+), 34 deletions(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index ad0931a89..c4af38426 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -365,7 +365,7 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = connection.LibvirtConnection(False) - conn.snapshot(instance_ref, recv_meta['id']) + conn.snapshot(self.context, instance_ref, recv_meta['id']) snapshot = image_service.show(context, recv_meta['id']) self.assertEquals(snapshot['properties']['image_state'], 'available') @@ -405,7 +405,7 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = connection.LibvirtConnection(False) - conn.snapshot(instance_ref, recv_meta['id']) + conn.snapshot(self.context, instance_ref, recv_meta['id']) snapshot = image_service.show(context, recv_meta['id']) self.assertEquals(snapshot['properties']['image_state'], 'available') @@ -775,7 +775,7 @@ class LibvirtConnTestCase(test.TestCase): network_info = [(network, mapping)] try: - conn.spawn(instance, network_info) + conn.spawn(context.get_admin_context(), instance, network_info) except Exception, e: count = (0 <= str(e.message).find('Unexpected method call')) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 199a8bc52..fd8416424 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -227,7 +227,7 @@ class XenAPIVMTestCase(test.TestCase): 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] instance = db.instance_create(self.context, values) - self.conn.spawn(instance, network_info) + self.conn.spawn(self.context, instance, network_info) gt1 = eventlet.spawn(_do_build, 1, self.project.id, self.user.id) gt2 = eventlet.spawn(_do_build, 2, self.project.id, self.user.id) @@ -257,14 +257,15 @@ class XenAPIVMTestCase(test.TestCase): instance = self._create_instance() name = "MySnapshot" - self.assertRaises(exception.Error, self.conn.snapshot, instance, name) + self.assertRaises(exception.Error, self.conn.snapshot, + self.context, instance, name) def test_instance_snapshot(self): stubs.stubout_instance_snapshot(self.stubs) instance = self._create_instance() name = "MySnapshot" - template_vm_ref = self.conn.snapshot(instance, name) + template_vm_ref = self.conn.snapshot(self.context, instance, name) def ensure_vm_was_torn_down(): vm_labels = [] @@ -422,7 +423,7 @@ class XenAPIVMTestCase(test.TestCase): 'label': 'fake', 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] - self.conn.spawn(instance, network_info) + self.conn.spawn(self.context, instance, network_info) self.create_vm_record(self.conn, os_type, instance_id) self.check_vm_record(self.conn, check_injection) self.assertTrue(instance.os_type) @@ -691,7 +692,7 @@ class XenAPIVMTestCase(test.TestCase): 'label': 'fake', 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] - self.conn.spawn(instance, network_info) + self.conn.spawn(self.context, instance, network_info) return instance @@ -802,8 +803,9 @@ class XenAPIMigrateInstance(test.TestCase): 'label': 'fake', 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] - conn.finish_resize(instance, dict(base_copy='hurr', cow='durr'), - network_info) + conn.finish_resize(self.context, instance, + dict(base_copy='hurr', cow='durr'), + network_info) class XenAPIDetermineDiskImageTestCase(test.TestCase): diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 66c79d465..3a142081c 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -28,8 +28,8 @@ from nova import utils def stubout_instance_snapshot(stubs): @classmethod - def fake_fetch_image(cls, session, instance_id, image, user, project, - type): + def fake_fetch_image(cls, context, session, instance_id, image, user, + project, type): from nova.virt.xenapi.fake import create_vdi name_label = "instance-%s" % instance_id #TODO: create fake SR record diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 34dc5f544..40cb877ce 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -61,7 +61,8 @@ class ComputeDriver(object): """Return a list of InstanceInfo for all registered VMs""" raise NotImplementedError() - def spawn(self, instance, network_info, block_device_mapping=None): + def spawn(self, context, instance, network_info, + block_device_mapping=None): """Launch a VM for the specified instance""" raise NotImplementedError() @@ -118,11 +119,11 @@ class ComputeDriver(object): off the instance copies over the COW disk""" raise NotImplementedError() - def snapshot(self, instance, image_id): + def snapshot(self, context, instance, image_id): """Create snapshot from a running VM instance.""" raise NotImplementedError() - def finish_resize(self, instance, disk_info): + def finish_resize(self, context, instance, disk_info): """Completes a resize, turning on the migrated instance""" raise NotImplementedError() diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 26bc421c0..f67c2309e 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -129,7 +129,8 @@ class FakeConnection(driver.ComputeDriver): info_list.append(self._map_to_instance_info(instance)) return info_list - def spawn(self, instance, network_info, block_device_mapping=None): + def spawn(self, context, instance, network_info, + block_device_mapping=None): """ Create a new instance/VM/domain on the virtualization platform. @@ -153,7 +154,7 @@ class FakeConnection(driver.ComputeDriver): fake_instance = FakeInstance(name, state) self.instances[name] = fake_instance - def snapshot(self, instance, name): + def snapshot(self, context, instance, name): """ Snapshots the specified instance. diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index 81c7dea58..8236b5a45 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -139,7 +139,8 @@ class HyperVConnection(driver.ComputeDriver): return instance_infos - def spawn(self, instance, network_info, block_device_mapping=None): + def spawn(self, context, instance, network_info, + block_device_mapping=None): """ Create a new VM and start it.""" vm = self._lookup(instance.name) if vm is not None: diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 96f9c41f9..9a964dfd2 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -399,7 +399,7 @@ class LibvirtConnection(driver.ComputeDriver): virt_dom.detachDevice(xml) @exception.wrap_exception() - def snapshot(self, instance, image_href): + def snapshot(self, context, instance, image_href): """Create snapshot from a running VM instance. This command only works with qemu 0.14+, the qemu_img flag is @@ -595,7 +595,8 @@ class LibvirtConnection(driver.ComputeDriver): # NOTE(ilyaalekseyev): Implementation like in multinics # for xenapi(tr3buchet) @exception.wrap_exception() - def spawn(self, instance, network_info, block_device_mapping=None): + def spawn(self, context, instance, network_info, + block_device_mapping=None): xml = self.to_xml(instance, False, network_info=network_info, block_device_mapping=block_device_mapping) block_device_mapping = block_device_mapping or [] diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 7e7d2dac3..5fa92230d 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -89,7 +89,7 @@ class VMWareVMOps(object): LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names))) return lst_vm_names - def spawn(self, instance, network_info): + def spawn(self, context, instance, network_info): """ Creates a VM instance. @@ -329,7 +329,7 @@ class VMWareVMOps(object): LOG.debug(_("Powered on the VM instance %s") % instance.name) _power_on_vm() - def snapshot(self, instance, snapshot_name): + def snapshot(self, context, instance, snapshot_name): """ Create snapshot from a running VM instance. Steps followed are: diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py index ce57847b2..3d209fa99 100644 --- a/nova/virt/vmwareapi_conn.py +++ b/nova/virt/vmwareapi_conn.py @@ -124,13 +124,14 @@ class VMWareESXConnection(driver.ComputeDriver): """List VM instances.""" return self._vmops.list_instances() - def spawn(self, instance, network_info, block_device_mapping=None): + def spawn(self, context, instance, network_info, + block_device_mapping=None): """Create VM instance.""" - self._vmops.spawn(instance, network_info) + self._vmops.spawn(context, instance, network_info) - def snapshot(self, instance, name): + def snapshot(self, context, instance, name): """Create snapshot from a running VM instance.""" - self._vmops.snapshot(instance, name) + self._vmops.snapshot(context, instance, name) def reboot(self, instance, network_info): """Reboot VM instance.""" diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 1c6604836..9d73cfb05 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -209,8 +209,8 @@ class VMOps(object): if instance.vm_mode != vm_mode: # Update database with normalized (or determined) value - db.instance_update(context.get_admin_context(), - instance['id'], {'vm_mode': vm_mode}) + db.instance_update(context, instance['id'], + {'vm_mode': vm_mode}) vm_ref = VMHelper.create_vm(self._session, instance, kernel and kernel.get('file', None) or None, ramdisk and ramdisk.get('file', None) or None, diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 7c355a55b..a1928dfa8 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -194,21 +194,22 @@ class XenAPIConnection(driver.ComputeDriver): def list_instances_detail(self): return self._vmops.list_instances_detail() - def spawn(self, instance, network_info, block_device_mapping=None): + def spawn(self, context, instance, network_info, + block_device_mapping=None): """Create VM instance""" - self._vmops.spawn(instance, network_info) + self._vmops.spawn(context, instance, network_info) def revert_resize(self, instance): """Reverts a resize, powering back on the instance""" self._vmops.revert_resize(instance) - def finish_resize(self, instance, disk_info, network_info): + def finish_resize(self, context, instance, disk_info, network_info): """Completes a resize, turning on the migrated instance""" - self._vmops.finish_resize(instance, disk_info, network_info) + self._vmops.finish_resize(context, instance, disk_info, network_info) - def snapshot(self, instance, image_id): + def snapshot(self, context, instance, image_id): """ Create snapshot from a running VM instance """ - self._vmops.snapshot(instance, image_id) + self._vmops.snapshot(context, instance, image_id) def reboot(self, instance, network_info): """Reboot VM instance""" -- cgit From 50eb566ba5ce50127ad3df8984dd6895c31361a3 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Wed, 27 Jul 2011 17:56:12 +0000 Subject: Fix context argument in a test; add TODOs --- nova/tests/test_libvirt.py | 2 +- nova/virt/driver.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index c4af38426..d4f8f00d8 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -775,7 +775,7 @@ class LibvirtConnTestCase(test.TestCase): network_info = [(network, mapping)] try: - conn.spawn(context.get_admin_context(), instance, network_info) + conn.spawn(self.context, instance, network_info) except Exception, e: count = (0 <= str(e.message).find('Unexpected method call')) diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 40cb877ce..8e17d7540 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -40,6 +40,7 @@ class ComputeDriver(object): def init_host(self, host): """Adopt existing VM's running here""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def get_info(self, instance_name): @@ -52,13 +53,16 @@ class ComputeDriver(object): :num_cpu: (int) the number of virtual CPUs for the domain :cpu_time: (int) the CPU time used in nanoseconds """ + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def list_instances(self): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def list_instances_detail(self): """Return a list of InstanceInfo for all registered VMs""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def spawn(self, context, instance, network_info, @@ -80,29 +84,36 @@ class ComputeDriver(object): warning in that case. """ + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def reboot(self, instance, network_info): """Reboot specified VM""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def snapshot_instance(self, context, instance_id, image_id): raise NotImplementedError() def get_console_pool_info(self, console_type): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def get_console_output(self, instance): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def get_ajax_console(self, instance): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def get_diagnostics(self, instance): """Return data about VM diagnostics""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def get_host_ip_addr(self): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def attach_volume(self, context, instance_id, volume_id, mountpoint): @@ -117,6 +128,7 @@ class ComputeDriver(object): def migrate_disk_and_power_off(self, instance, dest): """Transfers the VHD of a running instance to another host, then shuts off the instance copies over the COW disk""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def snapshot(self, context, instance, image_id): @@ -129,30 +141,37 @@ class ComputeDriver(object): def revert_resize(self, instance): """Reverts a resize, powering back on the instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def pause(self, instance, callback): """Pause VM instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def unpause(self, instance, callback): """Unpause paused VM instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def suspend(self, instance, callback): """suspend the specified instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def resume(self, instance, callback): """resume the specified instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def rescue(self, instance, callback, network_info): """Rescue the specified instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def unrescue(self, instance, callback, network_info): """Unrescue the specified instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def update_available_resource(self, ctxt, host): @@ -165,6 +184,7 @@ class ComputeDriver(object): :param host: hostname that compute manager is currently running """ + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def live_migration(self, ctxt, instance_ref, dest, @@ -184,20 +204,25 @@ class ComputeDriver(object): expected nova.compute.manager.recover_live_migration. """ + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def refresh_security_group_rules(self, security_group_id): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def refresh_security_group_members(self, security_group_id): + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def refresh_provider_fw_rules(self, security_group_id): """See: nova/virt/fake.py for docs.""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def reset_network(self, instance): """reset networking for specified instance""" + # TODO(Vek): Need to pass context in for access to auth_token pass def ensure_filtering_rules_for_instance(self, instance_ref): @@ -223,10 +248,12 @@ class ComputeDriver(object): :params instance_ref: nova.db.sqlalchemy.models.Instance object """ + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def unfilter_instance(self, instance, network_info): """Stop filtering instance""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def set_admin_password(self, context, instance_id, new_pass=None): @@ -237,24 +264,30 @@ class ComputeDriver(object): """Create a file on the VM instance. The file path and contents should be base64-encoded. """ + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def agent_update(self, instance, url, md5hash): """Update agent on the VM instance.""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def inject_network_info(self, instance, nw_info): """inject network info for specified instance""" + # TODO(Vek): Need to pass context in for access to auth_token pass def poll_rescued_instances(self, timeout): """Poll for rescued instances""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def set_host_enabled(self, host, enabled): """Sets the specified host's ability to accept new instances.""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() def plug_vifs(self, instance, network_info): """Plugs in VIFs to networks.""" + # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() -- cgit From 9a84b87ae04dc5220f95992d9a6c4e210fbc374f Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 13:59:53 -0400 Subject: fixed issue with factory for Versions Resource --- nova/api/openstack/versions.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 4d40274b3..c39e9dae7 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -104,9 +104,7 @@ class Versions(wsgi.Resource): @classmethod def factory(cls, global_config, **local_config): """Paste factory.""" - def _factory(app): - return cls(app, **local_config) - return _factory + return cls() def __init__(self): metadata = { -- cgit From f1830708f823a9de9c2f1cd24af5bed80302788f Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Wed, 27 Jul 2011 11:08:44 -0700 Subject: Some work on testing. Two cases related to lp816713 have some coverage already: using an id as an imageRef (test_create_instance_v1_1_local_href), and using a nova href as a url (test_create_instance_v1_1) --- nova/api/openstack/create_instance_helper.py | 4 +++- nova/tests/api/openstack/test_servers.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 0e6c0a87c..234c16bcc 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -89,7 +89,9 @@ class CreateInstanceHelper(object): image_href = self.controller._image_ref_from_req_data(body) # If the image href was generated by nova api, strip image_href # down to an id and use the default glance connection params - if image_href.startswith(req.application_url): + + if isinstance(image_href, basestring) and\ + image_href.startswith(req.application_url): image_href = image_href.split('/').pop() try: image_service, image_id = nova.image.get_image_service(image_href) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 4ca79434f..edc11b761 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1250,7 +1250,8 @@ class ServersTest(test.TestCase): def test_create_instance_v1_1(self): self._setup_for_create_instance() - image_href = 'http://localhost/images/2' + # proper local hrefs must start with 'http://localhost/v1.1/' + image_href = 'http://localhost/v1.1/images/2' flavor_ref = 'http://localhost/flavors/3' expected_flavor = { "id": "3", -- cgit From 4def65d37886fff0dc9f238bca5454abaacb6f76 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Wed, 27 Jul 2011 18:13:04 +0000 Subject: Use auth_token to set x-auth-token header in glance requests --- nova/virt/xenapi/vm_utils.py | 7 +++++-- plugins/xenserver/xenapi/etc/xapi.d/plugins/glance | 22 +++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index aa0e4c2df..b1b0ddd0c 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -377,7 +377,8 @@ class VMHelper(HelperBase): 'glance_host': glance_host, 'glance_port': glance_port, 'sr_path': cls.get_sr_path(session), - 'os_type': os_type} + 'os_type': os_type, + 'auth_token': getattr(context, 'auth_token', None)} kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'upload_vhd', kwargs) @@ -429,7 +430,8 @@ class VMHelper(HelperBase): 'glance_host': glance_host, 'glance_port': glance_port, 'uuid_stack': uuid_stack, - 'sr_path': cls.get_sr_path(session)} + 'sr_path': cls.get_sr_path(session), + 'auth_token': getattr(context, 'auth_token', None)} kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'download_vhd', kwargs) @@ -475,6 +477,7 @@ class VMHelper(HelperBase): sr_ref = safe_find_sr(session) glance_client, image_id = nova.image.get_glance_client(image) + glance_client.set_auth_token(getattr(context, 'auth_token', None)) meta, image_file = glance_client.get_image(image_id) virtual_size = int(meta['size']) vdi_size = virtual_size diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index fbe080b22..86e837849 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -67,12 +67,17 @@ def _copy_kernel_vdi(dest, copy_args): def _download_tarball(sr_path, staging_path, image_id, glance_host, - glance_port): + glance_port, auth_token): """Download the tarball image from Glance and extract it into the staging area. """ + # Build request headers + headers = {} + if auth_token: + headers['x-auth-token'] = auth_token + conn = httplib.HTTPConnection(glance_host, glance_port) - conn.request('GET', '/v1/images/%s' % image_id) + conn.request('GET', '/v1/images/%s' % image_id, headers=headers) resp = conn.getresponse() if resp.status == httplib.NOT_FOUND: raise Exception("Image '%s' not found in Glance" % image_id) @@ -236,7 +241,8 @@ def _prepare_staging_area_for_upload(sr_path, staging_path, vdi_uuids): os.link(source, link_name) -def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type): +def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type, + auth_token): """ Create a tarball of the image and then stream that into Glance using chunked-transfer-encoded HTTP. @@ -263,6 +269,10 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type): 'x-image-meta-container-format': 'ovf', 'x-image-meta-property-os-type': os_type} + # If we have an auth_token, set an x-auth-token header + if auth_token: + headers['x-auth-token'] = auth_token + for header, value in headers.iteritems(): conn.putheader(header, value) conn.endheaders() @@ -364,11 +374,12 @@ def download_vhd(session, args): glance_port = params["glance_port"] uuid_stack = params["uuid_stack"] sr_path = params["sr_path"] + auth_token = params["auth_token"] staging_path = _make_staging_area(sr_path) try: _download_tarball(sr_path, staging_path, image_id, glance_host, - glance_port) + glance_port, auth_token) # Right now, it's easier to return a single string via XenAPI, # so we'll json encode the list of VHDs. return json.dumps(_import_vhds(sr_path, staging_path, uuid_stack)) @@ -386,12 +397,13 @@ def upload_vhd(session, args): glance_port = params["glance_port"] sr_path = params["sr_path"] os_type = params["os_type"] + auth_token = params["auth_token"] staging_path = _make_staging_area(sr_path) try: _prepare_staging_area_for_upload(sr_path, staging_path, vdi_uuids) _upload_tarball(staging_path, image_id, glance_host, glance_port, - os_type) + os_type, auth_token) finally: _cleanup_staging_area(staging_path) -- cgit From 22beaf8802fdc44242f4a96e291c4fbb60af0e3a Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 14:24:35 -0400 Subject: make atom+xml accept header be ignored on 300 responses in the VersionsRequestDeserializer --- nova/api/openstack/versions.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index c39e9dae7..e063ff272 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -206,6 +206,14 @@ class VersionV11(object): class VersionsRequestDeserializer(wsgi.RequestDeserializer): + def get_expected_content_type(self, request): + supported_content_types = list(self.supported_content_types) + if request.path != '/': + # Remove atom+xml accept type for 300 responses + del supported_content_types[2] + + return request.best_match_content_type(supported_content_types) + def get_action_args(self, request_environment): """Parse dictionary created by routes library.""" args = {} -- cgit From e2ce48eb3ffde56fa8d74b397682814ad278ae63 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Wed, 27 Jul 2011 11:33:56 -0700 Subject: this change will require that local urls be input with a properly constructed local url: http://localhost/v1.1/images/[id]. Such urls are translated to ids at the api layer. Previously, any url ending with and int was ok. --- nova/tests/api/openstack/fakes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 26b1de818..a1d94876f 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -104,8 +104,7 @@ def stub_out_key_pair_funcs(stubs, have_key_pair=True): def stub_out_image_service(stubs): def fake_get_image_service(image_href): - image_id = int(str(image_href).split('/')[-1]) - return (nova.image.fake.FakeImageService(), image_id) + return (nova.image.fake.FakeImageService(), image_href) stubs.Set(nova.image, 'get_image_service', fake_get_image_service) stubs.Set(nova.image, 'get_default_image_service', lambda: nova.image.fake.FakeImageService()) -- cgit From c20a4845afc47d124017de698657c1713dc11e7f Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 14:35:47 -0400 Subject: fixed xmlns issue --- nova/api/openstack/versions.py | 8 ++++---- nova/tests/api/openstack/test_versions.py | 17 +++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index e063ff272..b38c48939 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -25,7 +25,7 @@ from nova.api.openstack import wsgi ATOM_XMLNS = "http://www.w3.org/2005/Atom" -OS_XMLNS_BASE = "http://docs.openstack.org/common/api/" +OS_XMLNS_BASE = "http://docs.openstack.org/common/api/v1.0" VERSIONS = { "v1.0": { "version": { @@ -235,7 +235,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _versions_to_xml(self, versions, name="versions", xmlns=None): root = self._xml_doc.createElement(name) - root.setAttribute("xmlns", "%sv1.0" % OS_XMLNS_BASE) + root.setAttribute("xmlns", OS_XMLNS_BASE) root.setAttribute("xmlns:atom", ATOM_XMLNS) for version in versions: @@ -256,7 +256,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _create_version_node(self, version, create_ns=False): version_node = self._xml_doc.createElement('version') if create_ns: - xmlns = "%s%s" % (OS_XMLNS_BASE, version['id']) + xmlns = OS_XMLNS_BASE xmlns_atom = "http://www.w3.org/2005/Atom" version_node.setAttribute('xmlns', xmlns) version_node.setAttribute('xmlns:atom', xmlns_atom) @@ -296,7 +296,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def multi(self, data): self._xml_doc = minidom.Document() node = self._versions_to_xml(data['choices'], 'choices', - xmlns="%sv1.0" % OS_XMLNS_BASE) + xmlns=OS_XMLNS_BASE) return self.to_xml_string(node) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 3f7867ff4..bc9000900 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -173,8 +173,7 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/xml") root = xml.etree.ElementTree.XML(res.body) self.assertEqual(root.tag.split('}')[1], "version") - self.assertEqual(root.tag.split('}')[0].strip('{'), - "%sv1.0" % OS_XMLNS_BASE) + self.assertEqual(root.tag.split('}')[0].strip('{'), OS_XMLNS_BASE) children = list(root) media_types = children[0] @@ -188,7 +187,7 @@ class VersionsTest(test.TestCase): expected = """ @@ -224,7 +223,7 @@ class VersionsTest(test.TestCase): expected = """ @@ -259,7 +258,7 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/xml") expected = """ - + @@ -451,7 +450,7 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/xml") expected = """ - + Date: Wed, 27 Jul 2011 15:29:15 -0400 Subject: update everything to use global VERSIONS --- nova/api/openstack/versions.py | 49 +++++++++++-------------------- nova/tests/api/openstack/test_versions.py | 18 ++++++------ 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index b38c48939..32ee64339 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -143,20 +143,14 @@ class Versions(wsgi.Resource): return self._versions_multi_choice(request) def _versions_list(self, request): - version_objs = [ - { - "id": "v1.1", - "status": "CURRENT", - #TODO(wwolf) get correct value for these - "updated": "2011-07-18T11:30:00Z", - }, - { - "id": "v1.0", - "status": "DEPRECATED", - #TODO(wwolf) get correct value for these - "updated": "2010-10-09T11:30:00Z", - }, - ] + version_objs = [] + for version in VERSIONS: + version = VERSIONS[version]['version'] + version_objs.append({ + "id": version['id'], + "status": version['status'], + "updated": version['updated'], + }) builder = nova.api.openstack.views.versions.get_view_builder(request) versions = [builder.build(version) for version in version_objs] @@ -164,28 +158,19 @@ class Versions(wsgi.Resource): def _versions_multi_choice(self, request): #TODO - version_objs = [ - { - "id": "v1.1", - "status": "CURRENT", + version_objs = [] + for version in VERSIONS: + version = VERSIONS[version]['version'] + version_objs.append({ + "id": version['id'], + "status": version['status'], "links": [ { - "rel": "self", + "rel": "self" } ], - "media-types": VERSIONS['v1.1']['version']['media-types'], - }, - { - "id": "v1.0", - "status": "DEPRECATED", - "links": [ - { - "rel": "self", - } - ], - "media-types": VERSIONS['v1.0']['version']['media-types'], - }, - ] + "media-types": version['media-types'] + }) builder = nova.api.openstack.views.versions.get_view_builder(request) choices = [ diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index bc9000900..f059b140d 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -53,7 +53,7 @@ class VersionsTest(test.TestCase): { "id": "v1.1", "status": "CURRENT", - "updated": "2011-07-18T11:30:00Z", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -63,7 +63,7 @@ class VersionsTest(test.TestCase): { "id": "v1.0", "status": "DEPRECATED", - "updated": "2010-10-09T11:30:00Z", + "updated": "2011-01-21T11:33:21Z", "links": [ { "rel": "self", @@ -259,11 +259,11 @@ class VersionsTest(test.TestCase): expected = """ - + + updated="2011-01-21T11:33:21Z"> """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, @@ -357,7 +357,7 @@ class VersionsTest(test.TestCase): expected = """ Available API Versions - 2011-07-18T11:30:00Z + 2011-01-21T11:33:21Z http://localhost/ Rackspace @@ -367,19 +367,19 @@ class VersionsTest(test.TestCase): http://localhost/v1.1/ Version v1.1 - 2011-07-18T11:30:00Z + 2011-01-21T11:33:21Z - Version v1.1 CURRENT (2011-07-18T11:30:00Z) + Version v1.1 CURRENT (2011-01-21T11:33:21Z) http://localhost/v1.0/ Version v1.0 - 2010-10-09T11:30:00Z + 2011-01-21T11:33:21Z - Version v1.0 DEPRECATED (2010-10-09T11:30:00Z) + Version v1.0 DEPRECATED (2011-01-21T11:33:21Z) -- cgit From f2d8e91b83ff3a3bd1e2f3c53c25a418a578cd27 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 16:34:02 -0400 Subject: moved rest of build logic into builder --- nova/api/openstack/versions.py | 42 ++-------------------------- nova/api/openstack/views/versions.py | 46 +++++++++++++++++++++---------- nova/tests/api/openstack/test_versions.py | 31 +++++++++++++-------- 3 files changed, 54 insertions(+), 65 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 32ee64339..fd0ee46b7 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -135,49 +135,13 @@ class Versions(wsgi.Resource): def dispatch(self, request, *args): """Respond to a request for all OpenStack API versions.""" + builder = nova.api.openstack.views.versions.get_view_builder(request) if request.path == '/': # List Versions - return self._versions_list(request) + return builder.build(VERSIONS) else: # Versions Multiple Choice - return self._versions_multi_choice(request) - - def _versions_list(self, request): - version_objs = [] - for version in VERSIONS: - version = VERSIONS[version]['version'] - version_objs.append({ - "id": version['id'], - "status": version['status'], - "updated": version['updated'], - }) - - builder = nova.api.openstack.views.versions.get_view_builder(request) - versions = [builder.build(version) for version in version_objs] - return dict(versions=versions) - - def _versions_multi_choice(self, request): - #TODO - version_objs = [] - for version in VERSIONS: - version = VERSIONS[version]['version'] - version_objs.append({ - "id": version['id'], - "status": version['status'], - "links": [ - { - "rel": "self" - } - ], - "media-types": version['media-types'] - }) - - builder = nova.api.openstack.views.versions.get_view_builder(request) - choices = [ - builder.build_choices(version, request) - for version in version_objs] - - return dict(choices=choices) + return builder.build_choices(VERSIONS, request) class VersionV10(object): diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index 97e35c983..87ec251e6 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -31,21 +31,37 @@ class ViewBuilder(object): """ self.base_url = base_url - def build_choices(self, version_data, request): - version_data['links'][0]['href'] = self._build_versioned_link(request, - version_data['id']) - return version_data - - def build(self, version_data): - """Generic method used to generate a version entity.""" - version = { - "id": version_data["id"], - "status": version_data["status"], - "updated": version_data["updated"], - "links": self._build_links(version_data), - } - - return version + def build_choices(self, VERSIONS, request): + version_objs = [] + for version in VERSIONS: + version = VERSIONS[version]['version'] + version_objs.append({ + "id": version['id'], + "status": version['status'], + "links": [ + { + "rel": "self", + "href": self._build_versioned_link(request, + version['id']) + } + ], + "media-types": version['media-types'] + }) + + return dict(choices=version_objs) + + def build(self, VERSIONS): + version_objs = [] + for version in VERSIONS: + version = VERSIONS[version]['version'] + version_objs.append({ + "id": version['id'], + "status": version['status'], + "updated": version['updated'], + "links": self._build_links(version), + }) + + return dict(versions=version_objs) def _build_versioned_link(self, req, version): return '%s://%s/%s%s' % (req.scheme, req.host, version, req.path) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index f059b140d..6e4042b3f 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -529,20 +529,29 @@ class VersionsTest(test.TestCase): base_url = "http://example.org/" version_data = { - "id": "3.2.1", - "status": "CURRENT", - "updated": "2011-07-18T11:30:00Z"} + "v3.2.1": { + "version": { + "id": "3.2.1", + "status": "CURRENT", + "updated": "2011-07-18T11:30:00Z", + } + } + } expected = { - "id": "3.2.1", - "status": "CURRENT", - "updated": "2011-07-18T11:30:00Z", - "links": [ + "versions": [ { - "rel": "self", - "href": "http://example.org/3.2.1/", - }, - ], + "id": "3.2.1", + "status": "CURRENT", + "updated": "2011-07-18T11:30:00Z", + "links": [ + { + "rel": "self", + "href": "http://example.org/3.2.1/", + }, + ], + } + ] } builder = views.versions.ViewBuilder(base_url) -- cgit From 9c220b1c4547ad2cdd6110fa029b6f9478bae99f Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 16:54:09 -0400 Subject: added test for accept header of atom+xml on 300 responses to make sure it defaults back to json, and reworked some of the logic to make how this happens clearer --- nova/api/openstack/versions.py | 3 ++- nova/tests/api/openstack/test_versions.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index fd0ee46b7..02b0e1df8 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -159,7 +159,8 @@ class VersionsRequestDeserializer(wsgi.RequestDeserializer): supported_content_types = list(self.supported_content_types) if request.path != '/': # Remove atom+xml accept type for 300 responses - del supported_content_types[2] + if 'application/atom+xml' in supported_content_types: + supported_content_types.remove('application/atom+xml') return request.best_match_content_type(supported_content_types) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 6e4042b3f..63bca7066 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -471,6 +471,16 @@ class VersionsTest(test.TestCase): """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, ATOM_XMLNS) + def test_multi_choice_server_atom(self): + """ + Make sure multi choice responses do not have content-type + application/atom+xml (should use default of json) + """ + req = webob.Request.blank('/servers/2') + req.accept = "application/atom+xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 300) + self.assertEqual(res.content_type, "application/json") def test_multi_choice_server(self): req = webob.Request.blank('/servers/2') -- cgit From 77d06c7c82bfafd956f1108b2adbcb378628511f Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 17:09:17 -0400 Subject: utilize _create_link_nodes base class function --- nova/api/openstack/versions.py | 11 +++-------- nova/api/openstack/wsgi.py | 2 ++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 02b0e1df8..928cf467a 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -220,14 +220,9 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): media_types = self._create_media_types(version['media-types']) version_node.appendChild(media_types) - for link in version['links']: - link_node = self._xml_doc.createElement('atom:link') - link_node.setAttribute('rel', link['rel']) - link_node.setAttribute('href', link['href']) - if 'type' in link: - link_node.setAttribute('type', link['type']) - - version_node.appendChild(link_node) + link_nodes = self._create_link_nodes(self._xml_doc, version['links']) + for link in link_nodes: + version_node.appendChild(link) return version_node diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index a28443d12..ca502021d 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -387,6 +387,8 @@ class XMLDictSerializer(DictSerializer): link_node = xml_doc.createElement('atom:link') link_node.setAttribute('rel', link['rel']) link_node.setAttribute('href', link['href']) + if 'type' in link: + link_node.setAttribute('type', link['type']) link_nodes.append(link_node) return link_nodes -- cgit From 22f502cdca94a20ebb061f434a9a78789a3b165d Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 17:19:59 -0400 Subject: move viewbuilder and serializer tests into their own test cases --- nova/tests/api/openstack/test_versions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 63bca7066..7bb762c71 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -535,6 +535,8 @@ class VersionsTest(test.TestCase): self.assertDictMatch(expected, json.loads(res.body)) + +class VersionsViewBuilderTests(VersionsTest): def test_view_builder(self): base_url = "http://example.org/" @@ -580,6 +582,8 @@ class VersionsTest(test.TestCase): self.assertEqual(actual, expected) + +class VersionsSerializerTests(VersionsTest): def test_versions_list_xml_serializer(self): versions_data = { 'versions': [ -- cgit From 9cc71286d6e5339e42d6957570bfc02ea71353fe Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 17:21:14 -0400 Subject: pep8 issue --- nova/tests/api/openstack/test_versions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 7bb762c71..1f2c1deef 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -471,6 +471,7 @@ class VersionsTest(test.TestCase): """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, ATOM_XMLNS) + def test_multi_choice_server_atom(self): """ Make sure multi choice responses do not have content-type -- cgit From c00e933be6500caf25d55d32db5abb0e36600670 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 17:54:35 -0400 Subject: put run_tests.sh back to how it was --- run_tests.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/run_tests.sh b/run_tests.sh index e39ecd315..8f2b51757 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -84,9 +84,7 @@ function run_pep8 { srcfiles+=" `find tools/*`" srcfiles+=" nova setup.py plugins/xenserver/xenapi/etc/xapi.d/plugins/glance" # Just run PEP8 in current environment - #${wrapper} pep8 --repeat --show-pep8 --show-source \ - #--exclude=vcsversion.py ${srcfiles} - pep8 --repeat --show-pep8 --show-source \ + ${wrapper} pep8 --repeat --show-pep8 --show-source \ --exclude=vcsversion.py ${srcfiles} } -- cgit From 634702e9a6813b8793a82ddd87d24690b05ffc1e Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 17:59:05 -0400 Subject: stub out VERSIONS for the tests --- nova/tests/api/openstack/test_versions.py | 75 ++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 1f2c1deef..dfbc67f15 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -29,7 +29,78 @@ from nova.api.openstack import views ATOM_XMLNS = versions.ATOM_XMLNS OS_XMLNS_BASE = versions.OS_XMLNS_BASE -VERSIONS = versions.VERSIONS +VERSIONS = { + "v1.0": { + "version": { + "id": "v1.0", + "status": "DEPRECATED", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.0/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" + } + ], + }, + }, + "v1.1": { + "version": { + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.1/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" + } + ], + }, + }, +} class VersionsTest(test.TestCase): @@ -38,6 +109,8 @@ class VersionsTest(test.TestCase): self.context = context.get_admin_context() self.stubs = stubout.StubOutForTesting() fakes.stub_out_auth(self.stubs) + #Stub out VERSIONS + versions.VERSIONS = VERSIONS def tearDown(self): super(VersionsTest, self).tearDown() -- cgit From 03aac3ffd546ab1528b73ee36c8632f30ed8af2f Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 27 Jul 2011 18:07:01 -0400 Subject: use ATOM_XMLNS everywhere --- nova/api/openstack/versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 928cf467a..95681b788 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -207,7 +207,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): version_node = self._xml_doc.createElement('version') if create_ns: xmlns = OS_XMLNS_BASE - xmlns_atom = "http://www.w3.org/2005/Atom" + xmlns_atom = ATOM_XMLNS version_node.setAttribute('xmlns', xmlns) version_node.setAttribute('xmlns:atom', xmlns_atom) -- cgit From 71414e65333692956023647b55be06de6a73f11f Mon Sep 17 00:00:00 2001 From: William Wolf Date: Thu, 28 Jul 2011 14:59:28 -0400 Subject: use wsgi XMLNS/ATOM vars --- nova/api/openstack/versions.py | 14 ++++++-------- nova/api/openstack/wsgi.py | 1 + nova/tests/api/openstack/test_versions.py | 32 +++++++++++++++---------------- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 95681b788..292043b94 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -24,8 +24,6 @@ import nova.api.openstack.views.versions from nova.api.openstack import wsgi -ATOM_XMLNS = "http://www.w3.org/2005/Atom" -OS_XMLNS_BASE = "http://docs.openstack.org/common/api/v1.0" VERSIONS = { "v1.0": { "version": { @@ -185,8 +183,8 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _versions_to_xml(self, versions, name="versions", xmlns=None): root = self._xml_doc.createElement(name) - root.setAttribute("xmlns", OS_XMLNS_BASE) - root.setAttribute("xmlns:atom", ATOM_XMLNS) + root.setAttribute("xmlns", wsgi.XMLNS_V11) + root.setAttribute("xmlns:atom", wsgi.XMLNS_ATOM) for version in versions: root.appendChild(self._create_version_node(version)) @@ -206,8 +204,8 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def _create_version_node(self, version, create_ns=False): version_node = self._xml_doc.createElement('version') if create_ns: - xmlns = OS_XMLNS_BASE - xmlns_atom = ATOM_XMLNS + xmlns = wsgi.XMLNS_V11 + xmlns_atom = wsgi.XMLNS_ATOM version_node.setAttribute('xmlns', xmlns) version_node.setAttribute('xmlns:atom', xmlns_atom) @@ -241,7 +239,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): def multi(self, data): self._xml_doc = minidom.Document() node = self._versions_to_xml(data['choices'], 'choices', - xmlns=OS_XMLNS_BASE) + xmlns=wsgi.XMLNS_V11) return self.to_xml_string(node) @@ -257,7 +255,7 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): def __init__(self, metadata=None, xmlns=None): self.metadata = metadata or {} if not xmlns: - self.xmlns = ATOM_XMLNS + self.xmlns = wsgi.XMLNS_ATOM else: self.xmlns = xmlns diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index ca502021d..c6ece7d45 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') diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index dfbc67f15..5d3b3d743 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -26,9 +26,8 @@ from nova import test from nova.tests.api.openstack import fakes from nova.api.openstack import versions from nova.api.openstack import views +from nova.api.openstack import wsgi -ATOM_XMLNS = versions.ATOM_XMLNS -OS_XMLNS_BASE = versions.OS_XMLNS_BASE VERSIONS = { "v1.0": { "version": { @@ -246,7 +245,7 @@ class VersionsTest(test.TestCase): self.assertEqual(res.content_type, "application/xml") root = xml.etree.ElementTree.XML(res.body) self.assertEqual(root.tag.split('}')[1], "version") - self.assertEqual(root.tag.split('}')[0].strip('{'), OS_XMLNS_BASE) + self.assertEqual(root.tag.split('}')[0].strip('{'), wsgi.XMLNS_V11) children = list(root) media_types = children[0] @@ -282,7 +281,7 @@ class VersionsTest(test.TestCase): api/v1.0/application.wadl" rel="describedby" type="application/vnd.sun.wadl+xml"/> - """.replace(" ", "").replace("\n", "") % OS_XMLNS_BASE + """.replace(" ", "").replace("\n", "") % wsgi.XMLNS_V11 actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -318,7 +317,7 @@ class VersionsTest(test.TestCase): api/v1.1/application.wadl" rel="describedby" type="application/vnd.sun.wadl+xml"/> - """.replace(" ", "").replace("\n", "") % OS_XMLNS_BASE + """.replace(" ", "").replace("\n", "") % wsgi.XMLNS_V11 actual = res.body.replace(" ", "").replace("\n", "") self.assertEqual(expected, actual) @@ -339,8 +338,8 @@ class VersionsTest(test.TestCase): updated="2011-01-21T11:33:21Z"> - """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, - ATOM_XMLNS) + """.replace(" ", "").replace("\n", "") % (wsgi.XMLNS_V11, + wsgi.XMLNS_ATOM) actual = res.body.replace(" ", "").replace("\n", "") @@ -542,8 +541,8 @@ class VersionsTest(test.TestCase): - """.replace(" ", "").replace("\n", "") % (OS_XMLNS_BASE, - ATOM_XMLNS) + """.replace(" ", "").replace("\n", "") % (wsgi.XMLNS_V11, + wsgi.XMLNS_ATOM) def test_multi_choice_server_atom(self): """ @@ -610,7 +609,7 @@ class VersionsTest(test.TestCase): self.assertDictMatch(expected, json.loads(res.body)) -class VersionsViewBuilderTests(VersionsTest): +class VersionsViewBuilderTests(test.TestCase): def test_view_builder(self): base_url = "http://example.org/" @@ -657,7 +656,7 @@ class VersionsViewBuilderTests(VersionsTest): self.assertEqual(actual, expected) -class VersionsSerializerTests(VersionsTest): +class VersionsSerializerTests(test.TestCase): def test_versions_list_xml_serializer(self): versions_data = { 'versions': [ @@ -680,7 +679,7 @@ class VersionsSerializerTests(VersionsTest): root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "versions") - self.assertEqual(root.tag.split('}')[0].strip('{'), OS_XMLNS_BASE) + self.assertEqual(root.tag.split('}')[0].strip('{'), wsgi.XMLNS_V11) version = list(root)[0] self.assertEqual(version.tag.split('}')[1], "version") self.assertEqual(version.get('id'), @@ -691,7 +690,7 @@ class VersionsSerializerTests(VersionsTest): link = list(version)[0] self.assertEqual(link.tag.split('}')[1], "link") - self.assertEqual(link.tag.split('}')[0].strip('{'), ATOM_XMLNS) + self.assertEqual(link.tag.split('}')[0].strip('{'), wsgi.XMLNS_ATOM) for key, val in versions_data['versions'][0]['links'][0].items(): self.assertEqual(link.get(key), val) @@ -718,7 +717,7 @@ class VersionsSerializerTests(VersionsTest): root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "choices") - self.assertEqual(root.tag.split('}')[0].strip('{'), OS_XMLNS_BASE) + self.assertEqual(root.tag.split('}')[0].strip('{'), wsgi.XMLNS_V11) version = list(root)[0] self.assertEqual(version.tag.split('}')[1], "version") self.assertEqual(version.get('id'), versions_data['choices'][0]['id']) @@ -739,7 +738,7 @@ class VersionsSerializerTests(VersionsTest): link = list(version)[1] self.assertEqual(link.tag.split('}')[1], "link") - self.assertEqual(link.tag.split('}')[0].strip('{'), ATOM_XMLNS) + self.assertEqual(link.tag.split('}')[0].strip('{'), wsgi.XMLNS_ATOM) for key, val in versions_data['choices'][0]['links'][0].items(): self.assertEqual(link.get(key), val) @@ -785,8 +784,7 @@ class VersionsSerializerTests(VersionsTest): root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "version") - self.assertEqual(root.tag.split('}')[0].strip('{'), - "http://docs.openstack.org/common/api/v1.0") + self.assertEqual(root.tag.split('}')[0].strip('{'), wsgi.XMLNS_V11) children = list(root) media_types = children[0] -- cgit From 1c2ac1e7646d1432f57104c6ee3d1fa434387741 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Thu, 28 Jul 2011 15:48:30 -0400 Subject: refactoring and make self links correct (not hard coded) --- nova/api/openstack/versions.py | 136 +++++++++++----------- nova/api/openstack/views/versions.py | 33 ++++-- nova/tests/api/openstack/test_versions.py | 186 +++++++++++++++--------------- 3 files changed, 178 insertions(+), 177 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 292043b94..b546462d4 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -26,74 +26,70 @@ from nova.api.openstack import wsgi VERSIONS = { "v1.0": { - "version": { - "id": "v1.0", - "status": "DEPRECATED", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.0/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" - }, - ], - "media-types": [ - { - "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.0+xml" - }, - { - "base": "application/json", - "type": "application/vnd.openstack.compute-v1.0+json" - } - ], - }, + "id": "v1.0", + "status": "DEPRECATED", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" + } + ], }, "v1.1": { - "version": { - "id": "v1.1", - "status": "CURRENT", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" - }, - ], - "media-types": [ - { - "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.1+xml" - }, - { - "base": "application/json", - "type": "application/vnd.openstack.compute-v1.1+json" - } - ], - }, + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" + } + ], }, } @@ -136,7 +132,7 @@ class Versions(wsgi.Resource): builder = nova.api.openstack.views.versions.get_view_builder(request) if request.path == '/': # List Versions - return builder.build(VERSIONS) + return builder.build_versions(VERSIONS) else: # Versions Multiple Choice return builder.build_choices(VERSIONS, request) @@ -144,12 +140,14 @@ class Versions(wsgi.Resource): class VersionV10(object): def show(self, req): - return VERSIONS['v1.0'] + builder = nova.api.openstack.views.versions.get_view_builder(req) + return builder.build_version(VERSIONS['v1.0']) class VersionV11(object): def show(self, req): - return VERSIONS['v1.1'] + builder = nova.api.openstack.views.versions.get_view_builder(req) + return builder.build_version(VERSIONS['v1.1']) class VersionsRequestDeserializer(wsgi.RequestDeserializer): diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index 87ec251e6..7673ffe9e 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -31,18 +31,17 @@ class ViewBuilder(object): """ self.base_url = base_url - def build_choices(self, VERSIONS, request): + def build_choices(self, VERSIONS, req): version_objs = [] for version in VERSIONS: - version = VERSIONS[version]['version'] + version = VERSIONS[version] version_objs.append({ "id": version['id'], "status": version['status'], "links": [ { "rel": "self", - "href": self._build_versioned_link(request, - version['id']) + "href": self.generate_href(version['id'], req.path) } ], "media-types": version['media-types'] @@ -50,10 +49,10 @@ class ViewBuilder(object): return dict(choices=version_objs) - def build(self, VERSIONS): + def build_versions(self, versions): version_objs = [] - for version in VERSIONS: - version = VERSIONS[version]['version'] + for version in versions: + version = versions[version] version_objs.append({ "id": version['id'], "status": version['status'], @@ -63,8 +62,13 @@ class ViewBuilder(object): return dict(versions=version_objs) - def _build_versioned_link(self, req, version): - return '%s://%s/%s%s' % (req.scheme, req.host, version, req.path) + def build_version(self, version): + + for link in version['links']: + if link['rel'] == 'self': + link['href'] = self.base_url.rstrip('/') + '/' + + return dict(version=version) def _build_links(self, version_data): """Generate a container of links that refer to the provided version.""" @@ -73,12 +77,17 @@ class ViewBuilder(object): links = [ { "rel": "self", - "href": href, + "href": href }, ] return links - def generate_href(self, version_number): + def generate_href(self, version_number, path=None): """Create an url that refers to a specific version_number.""" - return os.path.join(self.base_url, version_number) + '/' + version_number = version_number.strip('/') + if path: + path = path.strip('/') + return os.path.join(self.base_url, version_number, path) + else: + return os.path.join(self.base_url, version_number) + '/' diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 5d3b3d743..1373f2e39 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -30,74 +30,70 @@ from nova.api.openstack import wsgi VERSIONS = { "v1.0": { - "version": { - "id": "v1.0", - "status": "DEPRECATED", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.0/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" - }, - ], - "media-types": [ - { - "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.0+xml" - }, - { - "base": "application/json", - "type": "application/vnd.openstack.compute-v1.0+json" - } - ], - }, + "id": "v1.0", + "status": "DEPRECATED", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" + } + ], }, "v1.1": { - "version": { - "id": "v1.1", - "status": "CURRENT", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" - }, - ], - "media-types": [ - { - "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.1+xml" - }, - { - "base": "application/json", - "type": "application/vnd.openstack.compute-v1.1+json" - } - ], - }, + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" + } + ], }, } @@ -160,7 +156,7 @@ class VersionsTest(test.TestCase): "links": [ { "rel": "self", - "href": "http://servers.api.openstack.org/v1.0/" + "href": "http://localhost/v1.0/" }, { "rel": "describedby", @@ -206,7 +202,7 @@ class VersionsTest(test.TestCase): "links": [ { "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/" + "href": "http://localhost/v1.1/" }, { "rel": "describedby", @@ -269,7 +265,7 @@ class VersionsTest(test.TestCase): type="application/vnd.openstack.compute-v1.0+json"/> - - About This Version 2011-01-21T11:33:21Z - http://servers.api.openstack.org/v1.0/ + http://localhost/v1.0/ Rackspace http://www.rackspace.com/ - + - http://servers.api.openstack.org/v1.0/ + http://localhost/v1.0/ Version v1.0 2011-01-21T11:33:21Z - About This Version 2011-01-21T11:33:21Z - http://servers.api.openstack.org/v1.1/ + http://localhost/v1.1/ Rackspace http://www.rackspace.com/ - + - http://servers.api.openstack.org/v1.1/ + http://localhost/v1.1/ Version v1.1 2011-01-21T11:33:21Z - - + @@ -539,7 +535,7 @@ class VersionsTest(test.TestCase): - + """.replace(" ", "").replace("\n", "") % (wsgi.XMLNS_V11, wsgi.XMLNS_ATOM) @@ -569,7 +565,7 @@ class VersionsTest(test.TestCase): "status": "CURRENT", "links": [ { - "href": "http://localhost:80/v1.1/servers/2", + "href": "http://localhost/v1.1/servers/2", "rel": "self", }, ], @@ -589,7 +585,7 @@ class VersionsTest(test.TestCase): "status": "DEPRECATED", "links": [ { - "href": "http://localhost:80/v1.0/servers/2", + "href": "http://localhost/v1.0/servers/2", "rel": "self", }, ], @@ -615,11 +611,9 @@ class VersionsViewBuilderTests(test.TestCase): version_data = { "v3.2.1": { - "version": { - "id": "3.2.1", - "status": "CURRENT", - "updated": "2011-07-18T11:30:00Z", - } + "id": "3.2.1", + "status": "CURRENT", + "updated": "2011-07-18T11:30:00Z", } } @@ -640,7 +634,7 @@ class VersionsViewBuilderTests(test.TestCase): } builder = views.versions.ViewBuilder(base_url) - output = builder.build(version_data) + output = builder.build_versions(version_data) self.assertEqual(output, expected) @@ -701,7 +695,7 @@ class VersionsSerializerTests(test.TestCase): "id": "2.7.1", "updated": "2011-07-18T11:30:00Z", "status": "DEPRECATED", - "media-types": VERSIONS['v1.1']['version']['media-types'], + "media-types": VERSIONS['v1.1']['media-types'], "links": [ { "rel": "self", @@ -751,7 +745,7 @@ class VersionsSerializerTests(test.TestCase): "links": [ { "rel": "self", - "href": "http://servers.api.openstack.org/v1.0/" + "href": "http://localhost/v1.0/" }, { "rel": "describedby", @@ -886,7 +880,7 @@ class VersionsSerializerTests(test.TestCase): "links": [ { "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/" + "href": "http://localhost/v1.1/" }, { "rel": "describedby", @@ -936,7 +930,7 @@ class VersionsSerializerTests(test.TestCase): self.assertEqual(updated.tag.split('}')[1], 'updated') self.assertEqual(updated.text, '2011-01-21T11:33:21Z') self.assertEqual(id.tag.split('}')[1], 'id') - self.assertEqual(id.text, 'http://servers.api.openstack.org/v1.1/') + self.assertEqual(id.text, 'http://localhost/v1.1/') self.assertEqual(author.tag.split('}')[1], 'author') author_name = list(author)[0] @@ -947,7 +941,7 @@ class VersionsSerializerTests(test.TestCase): self.assertEqual(author_uri.text, 'http://www.rackspace.com/') self.assertEqual(link.get('href'), - 'http://servers.api.openstack.org/v1.1/') + 'http://localhost/v1.1/') self.assertEqual(link.get('rel'), 'self') self.assertEqual(entry.tag.split('}')[1], 'entry') @@ -960,7 +954,7 @@ class VersionsSerializerTests(test.TestCase): self.assertEqual(entry_id.tag.split('}')[1], "id") self.assertEqual(entry_id.text, - "http://servers.api.openstack.org/v1.1/") + "http://localhost/v1.1/") self.assertEqual(entry_title.tag.split('}')[1], "title") self.assertEqual(entry_title.get('type'), "text") self.assertEqual(entry_title.text, "Version v1.1") -- cgit From c0355038b462cfd75b423a535601c4463c68f80f Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Thu, 28 Jul 2011 21:00:38 +0000 Subject: Fix to_dict() and elevated() to preserve auth_token; revert an accidental change from context.get_admin_context() to simply context --- nova/context.py | 6 ++++-- nova/virt/xenapi/vmops.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/nova/context.py b/nova/context.py index a765d1695..a23a02a87 100644 --- a/nova/context.py +++ b/nova/context.py @@ -98,7 +98,8 @@ class RequestContext(object): 'read_deleted': self.read_deleted, 'remote_address': self.remote_address, 'timestamp': utils.isotime(self.timestamp), - 'request_id': self.request_id} + 'request_id': self.request_id, + 'auth_token': self.auth_token} @classmethod def from_dict(cls, values): @@ -112,7 +113,8 @@ class RequestContext(object): read_deleted, self.remote_address, self.timestamp, - self.request_id) + self.request_id, + self.auth_token) def get_admin_context(read_deleted=False): diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 57c035ffd..f7a800d58 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -209,8 +209,8 @@ class VMOps(object): if instance.vm_mode != vm_mode: # Update database with normalized (or determined) value - db.instance_update(context, instance['id'], - {'vm_mode': vm_mode}) + db.instance_update(context.get_admin_context(), + instance['id'], {'vm_mode': vm_mode}) vm_ref = VMHelper.create_vm(self._session, instance, kernel and kernel.get('file', None) or None, ramdisk and ramdisk.get('file', None) or None, -- cgit From 54f652bbffaf8edf9ccfe35e1e1b15c20327340a Mon Sep 17 00:00:00 2001 From: William Wolf Date: Thu, 28 Jul 2011 20:59:07 -0400 Subject: fixed pep8 issues and removed unnecessary factory function --- nova/api/openstack/versions.py | 15 +++++---------- nova/api/openstack/views/versions.py | 3 +-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index b546462d4..40e966c5f 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -38,13 +38,13 @@ VERSIONS = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl" }, ], "media-types": [ @@ -71,13 +71,13 @@ VERSIONS = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl" }, ], "media-types": [ @@ -95,12 +95,7 @@ VERSIONS = { class Versions(wsgi.Resource): - @classmethod - def factory(cls, global_config, **local_config): - """Paste factory.""" - return cls() - - def __init__(self): + eef __init__(self): metadata = { "attributes": { "version": ["status", "id"], diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index 7673ffe9e..cdf758b77 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -63,7 +63,6 @@ class ViewBuilder(object): return dict(versions=version_objs) def build_version(self, version): - for link in version['links']: if link['rel'] == 'self': link['href'] = self.base_url.rstrip('/') + '/' @@ -77,7 +76,7 @@ class ViewBuilder(object): links = [ { "rel": "self", - "href": href + "href": href, }, ] -- cgit From ad8d33165f52ddf14dc9bd745db00eb039d74af7 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Thu, 28 Jul 2011 21:00:55 -0400 Subject: fixed typo --- nova/api/openstack/versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 40e966c5f..607cf6a81 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -95,7 +95,7 @@ VERSIONS = { class Versions(wsgi.Resource): - eef __init__(self): + def __init__(self): metadata = { "attributes": { "version": ["status", "id"], -- cgit From eca19199bdfcc64948f41d7e6b1728cb17b3baa2 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Fri, 29 Jul 2011 10:08:20 -0400 Subject: fix more spacing issues, and removed self link from versions template data --- nova/api/openstack/versions.py | 8 ------ nova/api/openstack/views/versions.py | 12 +++++---- nova/tests/api/openstack/test_versions.py | 42 +++++++++++++------------------ run_tests.sh | 4 ++- 4 files changed, 28 insertions(+), 38 deletions(-) diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 607cf6a81..3ef72b7f6 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -30,10 +30,6 @@ VERSIONS = { "status": "DEPRECATED", "updated": "2011-01-21T11:33:21Z", "links": [ - { - "rel": "self", - "href": "" - }, { "rel": "describedby", "type": "application/pdf", @@ -63,10 +59,6 @@ VERSIONS = { "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", "links": [ - { - "rel": "self", - "href": "" - }, { "rel": "describedby", "type": "application/pdf", diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index cdf758b77..547289034 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import copy import os @@ -63,11 +64,12 @@ class ViewBuilder(object): return dict(versions=version_objs) def build_version(self, version): - for link in version['links']: - if link['rel'] == 'self': - link['href'] = self.base_url.rstrip('/') + '/' - - return dict(version=version) + reval = copy.deepcopy(version) + reval['links'].insert(0, { + "rel": "self", + "href": self.base_url.rstrip('/') + '/', + }) + return dict(version=reval) def _build_links(self, version_data): """Generate a container of links that refer to the provided version.""" diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 1373f2e39..e68455778 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -34,21 +34,17 @@ VERSIONS = { "status": "DEPRECATED", "updated": "2011-01-21T11:33:21Z", "links": [ - { - "rel": "self", - "href": "" - }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl" }, ], "media-types": [ @@ -67,21 +63,17 @@ VERSIONS = { "status": "CURRENT", "updated": "2011-01-21T11:33:21Z", "links": [ - { - "rel": "self", - "href": "" - }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl" }, ], "media-types": [ @@ -105,9 +97,11 @@ class VersionsTest(test.TestCase): self.stubs = stubout.StubOutForTesting() fakes.stub_out_auth(self.stubs) #Stub out VERSIONS + self.old_versions = versions.VERSIONS versions.VERSIONS = VERSIONS def tearDown(self): + versions.VERSIONS = self.old_versions super(VersionsTest, self).tearDown() def test_get_version_list(self): @@ -162,25 +156,25 @@ class VersionsTest(test.TestCase): "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl" } ], "media-types": [ { "base": "application/xml", "type": "application/" - "vnd.openstack.compute-v1.0+xml" + "vnd.openstack.compute-v1.0+xml" }, { "base": "application/json", "type": "application/" - "vnd.openstack.compute-v1.0+json" + "vnd.openstack.compute-v1.0+json" } ] } @@ -208,25 +202,25 @@ class VersionsTest(test.TestCase): "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl" } ], "media-types": [ { "base": "application/xml", "type": "application/" - "vnd.openstack.compute-v1.1+xml" + "vnd.openstack.compute-v1.1+xml" }, { "base": "application/json", "type": "application/" - "vnd.openstack.compute-v1.1+json" + "vnd.openstack.compute-v1.1+json" } ] } @@ -751,13 +745,13 @@ class VersionsSerializerTests(test.TestCase): "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl" }, ], "media-types": [ @@ -886,13 +880,13 @@ class VersionsSerializerTests(test.TestCase): "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf" }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl" }, ], "media-types": [ diff --git a/run_tests.sh b/run_tests.sh index 8f2b51757..e39ecd315 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -84,7 +84,9 @@ function run_pep8 { srcfiles+=" `find tools/*`" srcfiles+=" nova setup.py plugins/xenserver/xenapi/etc/xapi.d/plugins/glance" # Just run PEP8 in current environment - ${wrapper} pep8 --repeat --show-pep8 --show-source \ + #${wrapper} pep8 --repeat --show-pep8 --show-source \ + #--exclude=vcsversion.py ${srcfiles} + pep8 --repeat --show-pep8 --show-source \ --exclude=vcsversion.py ${srcfiles} } -- cgit From 6d62453f4834447f6c06a58ec52c1037d4142293 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Fri, 29 Jul 2011 10:54:20 -0400 Subject: fix run_tests.sh --- run_tests.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/run_tests.sh b/run_tests.sh index e39ecd315..8f2b51757 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -84,9 +84,7 @@ function run_pep8 { srcfiles+=" `find tools/*`" srcfiles+=" nova setup.py plugins/xenserver/xenapi/etc/xapi.d/plugins/glance" # Just run PEP8 in current environment - #${wrapper} pep8 --repeat --show-pep8 --show-source \ - #--exclude=vcsversion.py ${srcfiles} - pep8 --repeat --show-pep8 --show-source \ + ${wrapper} pep8 --repeat --show-pep8 --show-source \ --exclude=vcsversion.py ${srcfiles} } -- cgit From 1fb2a1b1f0b7a59193344103bdbb7d58b3a6e7c2 Mon Sep 17 00:00:00 2001 From: Jason Koelker Date: Fri, 29 Jul 2011 14:53:38 -0500 Subject: require either v4 or v6 --- bin/nova-manage | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 75d74903c..3c50e4fc8 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -662,8 +662,9 @@ class NetworkCommands(object): # check for certain required inputs if not label: raise exception.NetworkNotCreated(req='--label') - if not fixed_range_v4: - raise exception.NetworkNotCreated(req='--fixed_range_v4') + if not (fixed_range_v4 or fixed_range_v6): + req = '--fixed_range_v4 or --fixed_range_v6' + raise exception.NetworkNotCreated(req=req) bridge = bridge or FLAGS.flat_network_bridge if not bridge: -- cgit From 241bc43166dd174bd64ef4eda1ab368a5a312799 Mon Sep 17 00:00:00 2001 From: Jason Koelker Date: Fri, 29 Jul 2011 15:05:53 -0500 Subject: stwart the switch to just fixed_range --- bin/nova-manage | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 3c50e4fc8..1c3bd9984 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -632,6 +632,7 @@ class NetworkCommands(object): @args('--label', dest="label", metavar='