]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Deprecate the V1 API
authorMike Perez <thingee@gmail.com>
Sun, 16 Feb 2014 05:40:59 +0000 (21:40 -0800)
committerMike Perez <thingee@gmail.com>
Fri, 5 Sep 2014 03:24:37 +0000 (20:24 -0700)
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

18 files changed:
cinder/api/__init__.py
cinder/api/common.py
cinder/api/contrib/volume_host_attribute.py
cinder/api/contrib/volume_tenant_attribute.py
cinder/api/openstack/wsgi.py
cinder/api/versions.py
cinder/api/xmlutil.py
cinder/common/config.py
cinder/tests/api/contrib/test_services.py
cinder/tests/api/contrib/test_volume_host_attribute.py
cinder/tests/api/contrib/test_volume_tenant_attribute.py
cinder/tests/api/middleware/test_faults.py
cinder/tests/api/v1/test_volumes.py
cinder/tests/api/v2/test_volumes.py
cinder/tests/integrated/integrated_helpers.py
cinder/tests/integrated/test_volumes.py
cinder/tests/integrated/test_xml.py
etc/cinder/cinder.conf.sample

index a3a0371ebc924f3ba5e010ddd175d400a3b1cdab..0b9bda0fadc92023d4161773ac6ebb6516315859 100644 (file)
 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']
index ad7a8ddf72c19461e24f370895a681d49c93a1c1..2cfe4ec92bfb7c66e4bbdc09e232f970bd0f06d4 100644 (file)
@@ -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,
index 7c984c1544a9c34ade5e95ac71fc54223a27548f..d8a4c1dda6f0b2ca05de1be56013eed4677c7f69 100644 (file)
@@ -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):
index 04957e22632c18f1900f2cf1f48234c95e58830f..6932f4008b79ea1521b487759c560256ac0948d7 100644 (file)
@@ -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):
index 9e0c2102fdd5a73fba15dd183ef121378ddd9ec0..1fc08595128c8f6f07a46e47a634f9cb63deb95b 100644 (file)
@@ -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(),
index 885e731aebbeac87bcd47b76f7237e5a7a1a3477..ceb0fc1621813113b214ba0d0d63f24c2b52ac74 100644 (file)
@@ -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
 
index 65637806beb9bc548116576273289158a269c216..b52f72e460819902075003ebcff69820edba8313 100644 (file)
@@ -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'([^:{]*{[^}]*}[^:]*|[^:]+)')
index 36d88a569ef54dc26a3b1f15b789140a2e781086..3b0cf9373310260c239cb7563d867ac48cfbfa1d 100644 (file)
@@ -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.")),
index 8741f22f015c179020d9ea6305865abc2f95f182..35908849e4fb77779d96a8e819b3fd4f4ed7eb9f 100644 (file)
@@ -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)
 
index 1ff0aeee4e0225a3ed446f945f4b1a5818007f68..e675affe180c5cbdecf9f9e7b960497067dda88b 100644 (file)
@@ -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')
index 5323b741cc037e1f48f06a55ec98ef17cefe911c..cbf558195d339a62d896ec4b95193b736b111151 100644 (file)
@@ -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)
index 60297cf17fea5abaaaca60f41c2ff64efc638ed2..4464cb949440ed3a96f068a0311250dbe5331e28 100644 (file)
@@ -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("""
+                <badRequest code="400" xmlns="%s">
+                    <message>scram</message>
+                </badRequest>
+            """) % 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("""
+                <overLimit code="413" xmlns="%s">
+                    <message>sorry</message>
+                    <retryAfter>4</retryAfter>
+                </overLimit>
+            """) % 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("""
+                <itemNotFound code="404" xmlns="%s">
+                    <message>sorry</message>
+                </itemNotFound>
+            """) % common.XML_NS_V2)
+
+        self.assertEqual(expected.toxml(), actual.toxml())
index f597202f3c23eb5bcb13db605e4aff58a4d1127a..9eb8b011adb64ae42ce29c6d4ad7be0311a4bdf5 100644 (file)
@@ -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'
 
index 4369324686cc4c69e15378572264b9a67c45e876..ca94c4fea4e4abf91719525f2eb4d8808f86ec58 100644 (file)
@@ -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'
 
index 873b428bc569f286576887cddd0de0651e433615..118650ddb5c08605016d9d789c43963755507562 100644 (file)
@@ -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):
index 4ab011882d5902aa478bd6262030f154b845df1b..738470df68460b8ed9b3f1d4577fee52f7e111d7 100644 (file)
@@ -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')
index ca149b003798a005c4dec62418faa17a16a0e083..71bd4fc865b48d35a2eea87ab4c2f77451c066df 100644 (file)
@@ -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)
index d7e0838d7fe0516fe9ccccdc83ead9cc70a53479..646317930c7e496d70407a33b6e0a582488f2f0b 100644 (file)
 # 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)