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
This commit is contained in:
Mike Perez 2014-02-15 21:40:59 -08:00
parent e412605618
commit dce0424d90
18 changed files with 128 additions and 37 deletions

View File

@ -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']

View 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,

View 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):

View 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):

View 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(),

View 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

View 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'([^:{]*{[^}]*}[^:]*|[^:]+)')

View 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.")),

View 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)

View 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')

View 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)

View 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())

View 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'

View 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'

View 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):

View 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')

View 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)

View File

@ -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)