Deprecated networks related proxy APIs

This patch deprecates all the proxy APIs for networks. All those APIs
will return 404 in new Microversions.

The deprecated API endpoints are:
'/os-networks'
'/os-networks/add'
'/os-networks/{id}/action'

This patch doesn't bump the max API version, due to the patch separation.
The max API version will bump in the last patch.

Partially implements blueprint deprecate-api-proxies

Change-Id: Icfedbe7e4ff0a1b575ac4449ba11cf2383810866
This commit is contained in:
He Jie Xu
2016-06-23 14:56:42 +08:00
parent ea0befc7ca
commit f419c7bb59
5 changed files with 110 additions and 26 deletions

View File

@@ -17,6 +17,8 @@
import netaddr
from webob import exc
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import networks as schema
from nova.api.openstack import extensions
@@ -82,6 +84,7 @@ class NetworkController(wsgi.Controller):
def __init__(self, network_api=None):
self.network_api = network_api or network.API()
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors(())
def index(self, req):
context = req.environ['nova.context']
@@ -90,6 +93,7 @@ class NetworkController(wsgi.Controller):
result = [network_dict(context, net_ref) for net_ref in networks]
return {'networks': result}
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.response(202)
@extensions.expected_errors((404, 501))
@wsgi.action("disassociate")
@@ -105,6 +109,7 @@ class NetworkController(wsgi.Controller):
except NotImplementedError:
common.raise_feature_not_supported()
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors(404)
def show(self, req, id):
context = req.environ['nova.context']
@@ -117,6 +122,7 @@ class NetworkController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=msg)
return {'network': network_dict(context, network)}
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.response(202)
@extensions.expected_errors((404, 409))
def delete(self, req, id):
@@ -131,6 +137,7 @@ class NetworkController(wsgi.Controller):
msg = _("Network not found")
raise exc.HTTPNotFound(explanation=msg)
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors((400, 409, 501))
@validation.schema(schema.create)
def create(self, req, body):
@@ -155,6 +162,7 @@ class NetworkController(wsgi.Controller):
raise exc.HTTPConflict(explanation=ex.format_message())
return {"network": network_dict(context, network)}
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.response(202)
@extensions.expected_errors((400, 501))
@validation.schema(schema.add_network_to_project)

View File

@@ -12,6 +12,8 @@
from webob import exc
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import networks_associate
from nova.api.openstack import extensions
@@ -31,6 +33,7 @@ class NetworkAssociateActionController(wsgi.Controller):
def __init__(self, network_api=None):
self.network_api = network_api or network.API()
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.action("disassociate_host")
@wsgi.response(202)
@extensions.expected_errors((404, 501))
@@ -45,6 +48,7 @@ class NetworkAssociateActionController(wsgi.Controller):
except NotImplementedError:
common.raise_feature_not_supported()
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.action("disassociate_project")
@wsgi.response(202)
@extensions.expected_errors((404, 501))
@@ -59,6 +63,7 @@ class NetworkAssociateActionController(wsgi.Controller):
except NotImplementedError:
common.raise_feature_not_supported()
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.action("associate_host")
@wsgi.response(202)
@extensions.expected_errors((404, 501))

View File

@@ -20,6 +20,8 @@ from oslo_log import log as logging
import six
from webob import exc
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.compute.schemas import tenant_networks as schema
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
@@ -73,6 +75,7 @@ class TenantNetworkController(wsgi.Controller):
networks[n['id']] = n['label']
return [{'id': k, 'label': v} for k, v in six.iteritems(networks)]
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors(())
def index(self, req):
context = req.environ['nova.context']
@@ -83,6 +86,7 @@ class TenantNetworkController(wsgi.Controller):
networks.extend(self._default_networks)
return {'networks': [network_dict(n) for n in networks]}
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors(404)
def show(self, req, id):
context = req.environ['nova.context']
@@ -94,6 +98,7 @@ class TenantNetworkController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=msg)
return {'network': network_dict(network)}
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors((403, 404, 409))
@wsgi.response(202)
def delete(self, req, id):
@@ -129,6 +134,7 @@ class TenantNetworkController(wsgi.Controller):
if CONF.enable_network_quota and reservation:
QUOTAS.commit(context, reservation)
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@extensions.expected_errors((400, 403, 409, 503))
@validation.schema(schema.create)
def create(self, req, body):

View File

@@ -372,10 +372,9 @@ class NetworksTestV21(test.NoDBTestCase):
def test_network_disassociate(self):
uuid = FAKE_NETWORKS[0]['uuid']
res = self.controller._disassociate_host_and_project(
self.req, uuid, {'disassociate': None})
self._check_status(res, self.controller._disassociate_host_and_project,
202)
disassociate = self.controller._disassociate_host_and_project
res = disassociate(self.req, uuid, {'disassociate': None})
self._check_status(res, disassociate, 202)
self.assertIsNone(self.fake_network_api.networks[0]['project_id'])
self.assertIsNone(self.fake_network_api.networks[0]['host'])
@@ -403,8 +402,9 @@ class NetworksTestV21(test.NoDBTestCase):
self.controller.show, self.req, 100)
def test_network_delete(self):
res = self.controller.delete(self.req, 1)
self._check_status(res, self.controller.delete, 202)
delete_method = self.controller.delete
res = delete_method(self.req, 1)
self._check_status(res, delete_method, 202)
def test_network_delete_not_found(self):
self.assertRaises(webob.exc.HTTPNotFound,
@@ -416,8 +416,9 @@ class NetworksTestV21(test.NoDBTestCase):
def test_network_add(self):
uuid = FAKE_NETWORKS[1]['uuid']
res = self.controller.add(self.req, body={'id': uuid})
self._check_status(res, self.controller.add, 202)
add = self.controller.add
res = add(self.req, body={'id': uuid})
self._check_status(res, add, 202)
res_dict = self.controller.show(self.admin_req,
uuid)
self.assertEqual(res_dict['network']['project_id'],
@@ -458,8 +459,9 @@ class NetworksTestV21(test.NoDBTestCase):
'extra_arg': 123})
def test_network_add_network_with_none_id(self):
res = self.controller.add(self.req, body={'id': None})
self._check_status(res, self.controller.add, 202)
add = self.controller.add
res = add(self.req, body={'id': None})
self._check_status(res, add, 202)
def test_network_create(self):
res_dict = self.controller.create(self.req, body=self.new_network)
@@ -505,36 +507,37 @@ class NetworksAssociateTestV21(test.NoDBTestCase):
def test_network_disassociate_host_only(self):
uuid = FAKE_NETWORKS[0]['uuid']
res = self.associate_controller._disassociate_host_only(
disassociate = self.associate_controller._disassociate_host_only
res = disassociate(
self.req, uuid, {'disassociate_host': None})
self._check_status(res,
self.associate_controller._disassociate_host_only,
disassociate,
202)
self.assertIsNotNone(self.fake_network_api.networks[0]['project_id'])
self.assertIsNone(self.fake_network_api.networks[0]['host'])
def test_network_disassociate_project_only(self):
uuid = FAKE_NETWORKS[0]['uuid']
res = self.associate_controller._disassociate_project_only(
self.req, uuid, {'disassociate_project': None})
self._check_status(
res, self.associate_controller._disassociate_project_only, 202)
disassociate = self.associate_controller._disassociate_project_only
res = disassociate(self.req, uuid, {'disassociate_project': None})
self._check_status(res, disassociate, 202)
self.assertIsNone(self.fake_network_api.networks[0]['project_id'])
self.assertIsNotNone(self.fake_network_api.networks[0]['host'])
def test_network_disassociate_project_network_delete(self):
uuid = FAKE_NETWORKS[1]['uuid']
res = self.associate_controller._disassociate_project_only(
disassociate = self.associate_controller._disassociate_project_only
res = disassociate(
self.req, uuid, {'disassociate_project': None})
self._check_status(
res, self.associate_controller._disassociate_project_only, 202)
self._check_status(res, disassociate, 202)
self.assertIsNone(self.fake_network_api.networks[1]['project_id'])
res = self.controller.delete(self.req, 1)
delete = self.controller.delete
res = delete(self.req, 1)
# NOTE: On v2.1 code, delete method doesn't return anything and
# the status code is decorated on wsgi_code of the method.
self.assertIsNone(res)
self.assertEqual(202, self.controller.delete.wsgi_code)
self.assertEqual(202, delete.wsgi_code)
def test_network_associate_project_delete_fail(self):
uuid = FAKE_NETWORKS[0]['uuid']
@@ -544,9 +547,9 @@ class NetworksAssociateTestV21(test.NoDBTestCase):
def test_network_associate_with_host(self):
uuid = FAKE_NETWORKS[1]['uuid']
res = self.associate_controller._associate_host(
self.req, uuid, body={'associate_host': "TestHost"})
self._check_status(res, self.associate_controller._associate_host, 202)
associate = self.associate_controller._associate_host
res = associate(self.req, uuid, body={'associate_host': "TestHost"})
self._check_status(res, associate, 202)
res_dict = self.controller.show(self.admin_req, uuid)
self.assertEqual(res_dict['network']['host'], 'TestHost')
@@ -702,3 +705,44 @@ class NetworksAssociateEnforcementV21(test.NoDBTestCase):
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
class NetworksDeprecationTest(test.NoDBTestCase):
def setUp(self):
super(NetworksDeprecationTest, self).setUp()
self.controller = networks_v21.NetworkController()
self.req = fakes.HTTPRequest.blank('', version='2.36')
def test_all_api_return_not_found(self):
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.show, self.req, fakes.FAKE_UUID)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.delete, self.req, fakes.FAKE_UUID)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.index, self.req)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller._disassociate_host_and_project, self.req, {})
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.add, self.req, {})
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.create, self.req, {})
class NetworksAssociateDeprecationTest(test.NoDBTestCase):
def setUp(self):
super(NetworksAssociateDeprecationTest, self).setUp()
self.controller = networks_associate_v21\
.NetworkAssociateActionController()
self.req = fakes.HTTPRequest.blank('', version='2.36')
def test_all_api_return_not_found(self):
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller._associate_host, self.req, fakes.FAKE_UUID, {})
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller._disassociate_project_only, self.req,
fakes.FAKE_UUID, {})
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller._disassociate_host_only, self.req,
fakes.FAKE_UUID, {})

View File

@@ -127,11 +127,12 @@ class TenantNetworksTestV21(test.NoDBTestCase):
reserve_mock.return_value = 'rv'
res = self.controller.delete(self.req, 1)
delete_method = self.controller.delete
res = delete_method(self.req, 1)
# NOTE: on v2.1, http status code is set as wsgi_code of API
# method instead of status_int in a response object.
if isinstance(self.controller, networks_v21.TenantNetworkController):
status_int = self.controller.delete.wsgi_code
status_int = delete_method.wsgi_code
else:
status_int = res.status_int
self.assertEqual(202, status_int)
@@ -309,3 +310,23 @@ class TenantNetworksEnforcementV21(test.NoDBTestCase):
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
class TenantNetworksDeprecationTest(test.NoDBTestCase):
ctrlr = networks_v21.TenantNetworkController
validation_error = exception.ValidationError
def setUp(self):
super(TenantNetworksDeprecationTest, self).setUp()
self.controller = networks_v21.TenantNetworkController()
self.req = fakes.HTTPRequest.blank('', version='2.36')
def test_all_apis_return_not_found(self):
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.index, self.req)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.show, self.req, fakes.FAKE_UUID)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.delete, self.req, fakes.FAKE_UUID)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.create, self.req, {})