From dce0424d901476a85932cdce86276ae6e72797c9 Mon Sep 17 00:00:00 2001 From: Mike Perez Date: Sat, 15 Feb 2014 21:40:59 -0800 Subject: [PATCH] Deprecate the V1 API This gives a warning for using the V1 API in Juno and encourages users to switch to V2 before the K release where it will be removed. DocImpact Implements blueprint deprecate-v1-api Change-Id: I89eb9eb2a7819edb2a97b2ea2b5239a89124ca4d --- cinder/api/__init__.py | 10 ++- cinder/api/common.py | 3 +- cinder/api/contrib/volume_host_attribute.py | 2 +- cinder/api/contrib/volume_tenant_attribute.py | 2 +- cinder/api/openstack/wsgi.py | 9 +- cinder/api/versions.py | 6 +- cinder/api/xmlutil.py | 5 +- cinder/common/config.py | 2 +- cinder/tests/api/contrib/test_services.py | 8 +- .../api/contrib/test_volume_host_attribute.py | 4 +- .../contrib/test_volume_tenant_attribute.py | 4 +- cinder/tests/api/middleware/test_faults.py | 87 ++++++++++++++++++- cinder/tests/api/v1/test_volumes.py | 2 +- cinder/tests/api/v2/test_volumes.py | 2 +- cinder/tests/integrated/integrated_helpers.py | 2 +- cinder/tests/integrated/test_volumes.py | 12 +-- cinder/tests/integrated/test_xml.py | 3 +- etc/cinder/cinder.conf.sample | 2 +- 18 files changed, 128 insertions(+), 37 deletions(-) diff --git a/cinder/api/__init__.py b/cinder/api/__init__.py index a3a0371eb..0b9bda0fa 100644 --- a/cinder/api/__init__.py +++ b/cinder/api/__init__.py @@ -18,12 +18,20 @@ from oslo.config import cfg import paste.urlmap +from cinder.openstack.common.gettextutils import _ +from cinder.openstack.common import log as logging + CONF = cfg.CONF +LOG = logging.getLogger(__name__) def root_app_factory(loader, global_conf, **local_conf): - if not CONF.enable_v1_api: + if CONF.enable_v1_api: + LOG.warn(_('The v1 api is deprecated and will be removed after the ' + 'Juno release. You should set enable_v1_api=false and ' + 'enable_v2_api=true in your cinder.conf file.')) + else: del local_conf['/v1'] if not CONF.enable_v2_api: del local_conf['/v2'] diff --git a/cinder/api/common.py b/cinder/api/common.py index ad7a8ddf7..2cfe4ec92 100644 --- a/cinder/api/common.py +++ b/cinder/api/common.py @@ -46,7 +46,8 @@ CONF.register_opts(api_common_opts) LOG = logging.getLogger(__name__) -XML_NS_V1 = 'http://docs.openstack.org/volume/api/v1' +XML_NS_V1 = 'http://docs.openstack.org/api/openstack-block-storage/1.0/content' +XML_NS_V2 = 'http://docs.openstack.org/api/openstack-block-storage/2.0/content' # Regex that matches alphanumeric characters, periods, hypens, diff --git a/cinder/api/contrib/volume_host_attribute.py b/cinder/api/contrib/volume_host_attribute.py index 7c984c154..d8a4c1dda 100644 --- a/cinder/api/contrib/volume_host_attribute.py +++ b/cinder/api/contrib/volume_host_attribute.py @@ -57,7 +57,7 @@ class Volume_host_attribute(extensions.ExtensionDescriptor): name = "VolumeHostAttribute" alias = "os-vol-host-attr" namespace = ("http://docs.openstack.org/volume/ext/" - "volume_host_attribute/api/v1") + "volume_host_attribute/api/v2") updated = "2011-11-03T00:00:00+00:00" def get_controller_extensions(self): diff --git a/cinder/api/contrib/volume_tenant_attribute.py b/cinder/api/contrib/volume_tenant_attribute.py index 04957e226..6932f4008 100644 --- a/cinder/api/contrib/volume_tenant_attribute.py +++ b/cinder/api/contrib/volume_tenant_attribute.py @@ -55,7 +55,7 @@ class Volume_tenant_attribute(extensions.ExtensionDescriptor): name = "VolumeTenantAttribute" alias = "os-vol-tenant-attr" namespace = ("http://docs.openstack.org/volume/ext/" - "volume_tenant_attribute/api/v1") + "volume_tenant_attribute/api/v2") updated = "2011-11-03T00:00:00+00:00" def get_controller_extensions(self): diff --git a/cinder/api/openstack/wsgi.py b/cinder/api/openstack/wsgi.py index 9e0c2102f..1fc085951 100644 --- a/cinder/api/openstack/wsgi.py +++ b/cinder/api/openstack/wsgi.py @@ -33,8 +33,9 @@ from cinder import utils from cinder import wsgi -XMLNS_V1 = 'http://docs.openstack.org/volume/api/v1' -XMLNS_ATOM = 'http://www.w3.org/2005/Atom' +XML_NS_V1 = 'http://docs.openstack.org/api/openstack-block-storage/1.0/content' +XML_NS_V2 = 'http://docs.openstack.org/api/openstack-block-storage/2.0/content' +XML_NS_ATOM = 'http://www.w3.org/2005/Atom' LOG = logging.getLogger(__name__) @@ -1168,7 +1169,7 @@ class Fault(webob.exc.HTTPException): # 'code' is an attribute on the fault tag itself metadata = {'attributes': {fault_name: 'code'}} - xml_serializer = XMLDictSerializer(metadata, XMLNS_V1) + xml_serializer = XMLDictSerializer(metadata, XML_NS_V2) content_type = req.best_match_content_type() serializer = { @@ -1229,7 +1230,7 @@ class OverLimitFault(webob.exc.HTTPException): self.content['overLimitFault']['details'] = \ translate(self.content['overLimitFault']['details']) - xml_serializer = XMLDictSerializer(metadata, XMLNS_V1) + xml_serializer = XMLDictSerializer(metadata, XML_NS_V2) serializer = { 'application/xml': xml_serializer, 'application/json': JSONDictSerializer(), diff --git a/cinder/api/versions.py b/cinder/api/versions.py index 885e731ae..ceb0fc162 100644 --- a/cinder/api/versions.py +++ b/cinder/api/versions.py @@ -52,8 +52,8 @@ _KNOWN_VERSIONS = { }, "v1.0": { "id": "v1.0", - "status": "CURRENT", - "updated": "2012-01-04T11:33:21Z", + "status": "SUPPORTED", + "updated": "2014-06-28T12:20:21Z", "links": [ { "rel": "describedby", @@ -139,7 +139,7 @@ class AtomSerializer(wsgi.XMLDictSerializer): def __init__(self, metadata=None, xmlns=None): self.metadata = metadata or {} if not xmlns: - self.xmlns = wsgi.XMLNS_ATOM + self.xmlns = wsgi.XML_NS_ATOM else: self.xmlns = xmlns diff --git a/cinder/api/xmlutil.py b/cinder/api/xmlutil.py index 65637806b..b52f72e46 100644 --- a/cinder/api/xmlutil.py +++ b/cinder/api/xmlutil.py @@ -26,8 +26,9 @@ XMLNS_V10 = 'http://docs.rackspacecloud.com/servers/api/v1.0' XMLNS_V11 = 'http://docs.openstack.org/compute/api/v1.1' XMLNS_COMMON_V10 = 'http://docs.openstack.org/common/api/v1.0' XMLNS_ATOM = 'http://www.w3.org/2005/Atom' -XMLNS_VOLUME_V1 = 'http://docs.openstack.org/volume/api/v1' -XMLNS_VOLUME_V2 = ('http://docs.openstack.org/api/openstack-volume/2.0/' +XMLNS_VOLUME_V1 = ('http://docs.openstack.org/api/openstack-block-storage/1.0/' + 'content') +XMLNS_VOLUME_V2 = ('http://docs.openstack.org/api/openstack-block-storage/2.0/' 'content') _split_pattern = re.compile(r'([^:{]*{[^}]*}[^:]*|[^:]+)') diff --git a/cinder/common/config.py b/cinder/common/config.py index 36d88a569..3b0cf9373 100644 --- a/cinder/common/config.py +++ b/cinder/common/config.py @@ -116,7 +116,7 @@ global_opts = [ help='The topic that volume backup nodes listen on'), cfg.BoolOpt('enable_v1_api', default=True, - help=_("Deploy v1 of the Cinder API.")), + help=_("DEPRECATED: Deploy v1 of the Cinder API.")), cfg.BoolOpt('enable_v2_api', default=True, help=_("Deploy v2 of the Cinder API.")), diff --git a/cinder/tests/api/contrib/test_services.py b/cinder/tests/api/contrib/test_services.py index 8741f22f0..35908849e 100644 --- a/cinder/tests/api/contrib/test_services.py +++ b/cinder/tests/api/contrib/test_services.py @@ -400,27 +400,27 @@ class ServicesTest(test.TestCase): def test_services_enable_with_service_key(self): body = {'host': 'host1', 'service': 'cinder-volume'} - req = fakes.HTTPRequest.blank('/v1/fake/os-services/enable') + req = fakes.HTTPRequest.blank('/v2/fake/os-services/enable') res_dict = self.controller.update(req, "enable", body) self.assertEqual(res_dict['status'], 'enabled') def test_services_enable_with_binary_key(self): body = {'host': 'host1', 'binary': 'cinder-volume'} - req = fakes.HTTPRequest.blank('/v1/fake/os-services/enable') + req = fakes.HTTPRequest.blank('/v2/fake/os-services/enable') res_dict = self.controller.update(req, "enable", body) self.assertEqual(res_dict['status'], 'enabled') def test_services_disable_with_service_key(self): - req = fakes.HTTPRequest.blank('/v1/fake/os-services/disable') + req = fakes.HTTPRequest.blank('/v2/fake/os-services/disable') body = {'host': 'host1', 'service': 'cinder-volume'} res_dict = self.controller.update(req, "disable", body) self.assertEqual(res_dict['status'], 'disabled') def test_services_disable_with_binary_key(self): - req = fakes.HTTPRequest.blank('/v1/fake/os-services/disable') + req = fakes.HTTPRequest.blank('/v2/fake/os-services/disable') body = {'host': 'host1', 'binary': 'cinder-volume'} res_dict = self.controller.update(req, "disable", body) diff --git a/cinder/tests/api/contrib/test_volume_host_attribute.py b/cinder/tests/api/contrib/test_volume_host_attribute.py index 1ff0aeee4..e675affe1 100644 --- a/cinder/tests/api/contrib/test_volume_host_attribute.py +++ b/cinder/tests/api/contrib/test_volume_host_attribute.py @@ -121,7 +121,7 @@ class VolumeHostAttributeTest(test.TestCase): res = req.get_response(app()) vol = etree.XML(res.body) host_key = ('{http://docs.openstack.org/volume/ext/' - 'volume_host_attribute/api/v1}host') + 'volume_host_attribute/api/v2}host') self.assertEqual(vol.get(host_key), 'host001') def test_list_volumes_detail_xml(self): @@ -133,5 +133,5 @@ class VolumeHostAttributeTest(test.TestCase): res = req.get_response(app()) vol = list(etree.XML(res.body))[0] host_key = ('{http://docs.openstack.org/volume/ext/' - 'volume_host_attribute/api/v1}host') + 'volume_host_attribute/api/v2}host') self.assertEqual(vol.get(host_key), 'host001') diff --git a/cinder/tests/api/contrib/test_volume_tenant_attribute.py b/cinder/tests/api/contrib/test_volume_tenant_attribute.py index 5323b741c..cbf558195 100644 --- a/cinder/tests/api/contrib/test_volume_tenant_attribute.py +++ b/cinder/tests/api/contrib/test_volume_tenant_attribute.py @@ -121,7 +121,7 @@ class VolumeTenantAttributeTest(test.TestCase): res = req.get_response(app()) vol = etree.XML(res.body) tenant_key = ('{http://docs.openstack.org/volume/ext/' - 'volume_tenant_attribute/api/v1}tenant_id') + 'volume_tenant_attribute/api/v2}tenant_id') self.assertEqual(vol.get(tenant_key), PROJECT_ID) def test_list_volumes_detail_xml(self): @@ -133,5 +133,5 @@ class VolumeTenantAttributeTest(test.TestCase): res = req.get_response(app()) vol = list(etree.XML(res.body))[0] tenant_key = ('{http://docs.openstack.org/volume/ext/' - 'volume_tenant_attribute/api/v1}tenant_id') + 'volume_tenant_attribute/api/v2}tenant_id') self.assertEqual(vol.get(tenant_key), PROJECT_ID) diff --git a/cinder/tests/api/middleware/test_faults.py b/cinder/tests/api/middleware/test_faults.py index 60297cf17..4464cb949 100644 --- a/cinder/tests/api/middleware/test_faults.py +++ b/cinder/tests/api/middleware/test_faults.py @@ -186,14 +186,14 @@ class TestFaults(test.TestCase): self.assertEqual(fault.status_int, 400) def test_xml_serializer(self): - """Ensure that a v1.1 request responds with a v1 xmlns.""" - request = webob.Request.blank('/v1', + """Ensure that a v2 request responds with a v2 xmlns.""" + request = webob.Request.blank('/v2', headers={"Accept": "application/xml"}) fault = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='scram')) response = request.get_response(fault) - self.assertIn(common.XML_NS_V1, response.body) + self.assertIn(common.XML_NS_V2, response.body) self.assertEqual(response.content_type, "application/xml") self.assertEqual(response.status_int, 400) @@ -277,3 +277,84 @@ class FaultsXMLSerializationTestV11(test.TestCase): """) % common.XML_NS_V1) self.assertEqual(expected.toxml(), actual.toxml()) + + +class FaultsXMLSerializationTestV2(test.TestCase): + """Tests covering `cinder.api.openstack.faults:Fault` class.""" + + def _prepare_xml(self, xml_string): + xml_string = xml_string.replace(" ", "") + xml_string = xml_string.replace("\n", "") + xml_string = xml_string.replace("\t", "") + return xml_string + + def test_400_fault(self): + metadata = {'attributes': {"badRequest": 'code'}} + serializer = wsgi.XMLDictSerializer(metadata=metadata, + xmlns=common.XML_NS_V2) + + fixture = { + "badRequest": { + "message": "scram", + "code": 400, + }, + } + + output = serializer.serialize(fixture) + actual = minidom.parseString(self._prepare_xml(output)) + + expected = minidom.parseString(self._prepare_xml(""" + + scram + + """) % common.XML_NS_V2) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_413_fault(self): + metadata = {'attributes': {"overLimit": 'code'}} + serializer = wsgi.XMLDictSerializer(metadata=metadata, + xmlns=common.XML_NS_V2) + + fixture = { + "overLimit": { + "message": "sorry", + "code": 413, + "retryAfter": 4, + }, + } + + output = serializer.serialize(fixture) + actual = minidom.parseString(self._prepare_xml(output)) + + expected = minidom.parseString(self._prepare_xml(""" + + sorry + 4 + + """) % common.XML_NS_V2) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_404_fault(self): + metadata = {'attributes': {"itemNotFound": 'code'}} + serializer = wsgi.XMLDictSerializer(metadata=metadata, + xmlns=common.XML_NS_V2) + + fixture = { + "itemNotFound": { + "message": "sorry", + "code": 404, + }, + } + + output = serializer.serialize(fixture) + actual = minidom.parseString(self._prepare_xml(output)) + + expected = minidom.parseString(self._prepare_xml(""" + + sorry + + """) % common.XML_NS_V2) + + self.assertEqual(expected.toxml(), actual.toxml()) diff --git a/cinder/tests/api/v1/test_volumes.py b/cinder/tests/api/v1/test_volumes.py index f597202f3..9eb8b011a 100644 --- a/cinder/tests/api/v1/test_volumes.py +++ b/cinder/tests/api/v1/test_volumes.py @@ -33,7 +33,7 @@ from cinder import utils from cinder.volume import api as volume_api -NS = '{http://docs.openstack.org/volume/api/v1}' +NS = '{http://docs.openstack.org/api/openstack-block-storage/1.0/content}' TEST_SNAPSHOT_UUID = '00000000-0000-0000-0000-000000000001' diff --git a/cinder/tests/api/v2/test_volumes.py b/cinder/tests/api/v2/test_volumes.py index 436932468..ca94c4fea 100644 --- a/cinder/tests/api/v2/test_volumes.py +++ b/cinder/tests/api/v2/test_volumes.py @@ -36,7 +36,7 @@ from cinder.volume import api as volume_api CONF = cfg.CONF -NS = '{http://docs.openstack.org/api/openstack-volume/2.0/content}' +NS = '{http://docs.openstack.org/api/openstack-block-storage/2.0/content}' TEST_SNAPSHOT_UUID = '00000000-0000-0000-0000-000000000001' diff --git a/cinder/tests/integrated/integrated_helpers.py b/cinder/tests/integrated/integrated_helpers.py index 873b428bc..118650ddb 100644 --- a/cinder/tests/integrated/integrated_helpers.py +++ b/cinder/tests/integrated/integrated_helpers.py @@ -80,7 +80,7 @@ class _IntegratedTestBase(test.TestCase): self.osapi.start() # FIXME(ja): this is not the auth url - this is the service url # FIXME(ja): this needs fixed in nova as well - self.auth_url = 'http://%s:%s/v1' % (self.osapi.host, self.osapi.port) + self.auth_url = 'http://%s:%s/v2' % (self.osapi.host, self.osapi.port) LOG.warn(self.auth_url) def _get_flags(self): diff --git a/cinder/tests/integrated/test_volumes.py b/cinder/tests/integrated/test_volumes.py index 4ab011882..738470df6 100644 --- a/cinder/tests/integrated/test_volumes.py +++ b/cinder/tests/integrated/test_volumes.py @@ -35,7 +35,7 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): def _start_api_service(self): self.osapi = service.WSGIService("osapi_volume") self.osapi.start() - self.auth_url = 'http://%s:%s/v1' % (self.osapi.host, self.osapi.port) + self.auth_url = 'http://%s:%s/v2' % (self.osapi.host, self.osapi.port) LOG.warn(self.auth_url) def _get_flags(self): @@ -179,16 +179,16 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): def test_create_and_update_volume(self): # Create vol1 created_volume = self.api.post_volume({'volume': { - 'size': 1, 'display_name': 'vol1'}}) - self.assertEqual(created_volume['display_name'], 'vol1') + 'size': 1, 'name': 'vol1'}}) + self.assertEqual(created_volume['name'], 'vol1') created_volume_id = created_volume['id'] # update volume - body = {'volume': {'display_name': 'vol-one'}} + body = {'volume': {'name': 'vol-one'}} updated_volume = self.api.put_volume(created_volume_id, body) - self.assertEqual(updated_volume['display_name'], 'vol-one') + self.assertEqual(updated_volume['name'], 'vol-one') # check for update found_volume = self.api.get_volume(created_volume_id) self.assertEqual(created_volume_id, found_volume['id']) - self.assertEqual(found_volume['display_name'], 'vol-one') + self.assertEqual(found_volume['name'], 'vol-one') diff --git a/cinder/tests/integrated/test_xml.py b/cinder/tests/integrated/test_xml.py index ca149b003..71bd4fc86 100644 --- a/cinder/tests/integrated/test_xml.py +++ b/cinder/tests/integrated/test_xml.py @@ -38,7 +38,6 @@ class XmlTests(integrated_helpers._IntegratedTestBase): # self.assertEqual(root.nsmap.get(None), xmlutil.XMLNS_COMMON_V10) def test_namespace_volumes(self): - """/servers should have v1.1 namespace (has changed in 1.1).""" headers = {} headers['Accept'] = 'application/xml' @@ -47,4 +46,4 @@ class XmlTests(integrated_helpers._IntegratedTestBase): data = response.raw LOG.warn("data: %s" % data) root = etree.parse(data).getroot() - self.assertEqual(root.nsmap.get(None), common.XML_NS_V1) + self.assertEqual(root.nsmap.get(None), common.XML_NS_V2) diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index d7e0838d7..646317930 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -529,7 +529,7 @@ # The topic that volume backup nodes listen on (string value) #backup_topic=cinder-backup -# Deploy v1 of the Cinder API. (boolean value) +# DEPRECATED: Deploy v1 of the Cinder API. (boolean value) #enable_v1_api=true # Deploy v2 of the Cinder API. (boolean value) -- 2.45.2