From 1b71252a5fca825ef8d6889b431a3cf7932d6e03 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Sep 2019 22:27:15 +0100 Subject: [PATCH] Remove (most) '/os-networks' REST APIs Drop support for most of the 'os-networks' REST APIs excluding those that proxy through to neutron. This API now returns a 410 response for the non-proxy routes. Unit tests are removed for removed APIs and the functional API sample tests are just asserting the 410 response now same. The latter are also expanded to cover APIs that weren't previously tested. The API sample docs are left intact since the API reference still builds from those and can be considered more or less branchless, so people looking at the API reference can apply it to older deployments of nova before these APIs were removed. Note: yes, the API samples are correct. It really is a useless API when used with neutron. Change-Id: I68bfa77a520382317fc490a4f6c12dd62fc6dcda Signed-off-by: Stephen Finucane --- api-ref/source/os-networks.inc | 79 ++- .../os-networks/network-show-resp.json | 46 +- .../os-networks/networks-list-resp.json | 74 +-- nova/api/openstack/compute/networks.py | 86 +-- .../openstack/compute/networks_associate.py | 59 +- .../compute/rest_api_version_history.rst | 6 + .../api/openstack/compute/schemas/networks.py | 77 --- .../compute/schemas/networks_associate.py | 24 - nova/policies/__init__.py | 2 - nova/policies/networks.py | 26 - nova/policies/networks_associate.py | 50 -- .../network-associate-host-req.json.tpl | 3 - .../network-disassociate-host-req.json.tpl | 3 - .../network-disassociate-project-req.json.tpl | 3 - .../network-disassociate-req.json.tpl | 3 - .../os-networks/network-add-req.json.tpl | 3 - .../os-networks/network-create-req.json.tpl | 12 - .../os-networks/network-create-resp.json.tpl | 36 -- .../os-networks/network-show-resp.json.tpl | 44 +- .../os-networks/networks-list-resp.json.tpl | 70 +-- .../api_sample_tests/test_networks.py | 77 +-- .../test_networks_associate.py | 47 +- .../api/openstack/compute/test_networks.py | 513 +----------------- nova/tests/unit/fake_policy.py | 2 - nova/tests/unit/test_policy.py | 2 - .../remove-nova-network-c02953ba72a1795d.yaml | 9 + 26 files changed, 174 insertions(+), 1182 deletions(-) delete mode 100644 nova/api/openstack/compute/schemas/networks.py delete mode 100644 nova/api/openstack/compute/schemas/networks_associate.py delete mode 100644 nova/policies/networks_associate.py delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-associate-host-req.json.tpl delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-host-req.json.tpl delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-project-req.json.tpl delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-req.json.tpl delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks/network-add-req.json.tpl delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-req.json.tpl delete mode 100644 nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-resp.json.tpl diff --git a/api-ref/source/os-networks.inc b/api-ref/source/os-networks.inc index 99477e266d12..a9ee87f69ac7 100644 --- a/api-ref/source/os-networks.inc +++ b/api-ref/source/os-networks.inc @@ -1,28 +1,26 @@ .. -*- rst -*- -.. NOTE(sdague): These APIs are deprecated so do not update this - file even body, example or parameters are not complete. -===================================== +====================================== Networks (os-networks) (DEPRECATED) -===================================== +====================================== -.. warning:: The networks API was designed to work with - ``nova-network``. Some features are proxied to - ``neutron`` when appropriate, but as with all translation - proxies, this is far from perfect compatibility. These - APIs should be avoided in new applications in favor of - using ``neutron`` directly. These will fail with a 404 - starting from microversion 2.36. - See: `Relevant Network APIs - `__. +.. warning:: + This API was designed to work with ``nova-network`` which was deprecated in + the 14.0.0 (Newton) release and removed in the 21.0.0 (Ussuri) release. Some + features are proxied to the Network service (neutron) when appropriate, but + as with all translation proxies, this is far from perfect compatibility. + These APIs should be avoided in new applications in favor of `using + neutron directly`__. These will fail with a 404 starting from microversion + 2.36. They were removed in the 21.0.0 (Ussuri) release. + +__ https://docs.openstack.org/api-ref/network/v2/#networks Creates, lists, shows information for, and deletes networks. Adds network to a project, disassociates a network from a project, and disassociates a project from a network. - Associates host with and disassociates host from a network. List Networks @@ -60,7 +58,8 @@ these permissions through the ``policy.json`` file. Normal response codes: 200 -Error response codes: badRequest(400), unauthorized(401), forbidden(403), conflict(409), NotImplemented(501) +Error response codes: badRequest(400), unauthorized(401), forbidden(403), +conflict(409), gone(410), notImplemented(501) Request ------- @@ -91,7 +90,8 @@ this operation. Cloud providers can change these permissions through the Normal response codes: 202 -Error response codes: badRequest(400), unauthorized(401), forbidden(403), NotImplemented(501) +Error response codes: badRequest(400), unauthorized(401), forbidden(403), +gone(410), notImplemented(501) Request ------- @@ -146,7 +146,8 @@ these permissions through the ``policy.json`` file. Normal response codes: 202 -Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), conflict(409) +Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), +conflict(409), gone(410) Request ------- @@ -160,15 +161,11 @@ Response There is no body content for the response of a successful DELETE query. -Associate Host (DEPRECATED) -=========================== +Associate Host +============== .. rest_method:: POST /os-networks/{network_id}/action -.. warning:: - This API is only available with ``nova-network`` which is - deprecated. It should be avoided in any new applications. - Associates a network with a host. Specify the ``associate_host`` action in the request body. @@ -179,7 +176,8 @@ permissions through the ``policy.json`` file. Normal response codes: 202 -Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), NotImplemented(501) +Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), +gone(410), notImplemented(501) Request ------- @@ -199,15 +197,11 @@ Response There is no body content for the response of a successful POST query. -Disassociate Network (DEPRECATED) -================================= +Disassociate Network +==================== .. rest_method:: POST /os-networks/{network_id}/action -.. warning:: - This API is only available with ``nova-network`` which is - deprecated. It should be avoided in any new applications. - Disassociates a network from a project. You can then reuse the network. Specify the ``disassociate`` action in the request body. @@ -218,7 +212,8 @@ these permissions through the ``policy.json`` file. Normal response codes: 202 -Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), NotImplemented(501) +Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), +gone(410), notImplemented(501) Request ------- @@ -237,15 +232,11 @@ Response There is no body content for the response of a successful POST query. -Disassociate Host (DEPRECATED) -============================== +Disassociate Host +================= .. rest_method:: POST /os-networks/{network_id}/action -.. warning:: - This API is only available with ``nova-network`` which is - deprecated. It should be avoided in any new applications. - Disassociates a host from a network. Specify the ``disassociate_host`` action in the request body. @@ -256,7 +247,8 @@ these permissions through the ``policy.json`` file. Normal response codes: 202 -Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), NotImplemented(501) +Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), +gone(410), notImplemented(501) Request ------- @@ -276,15 +268,11 @@ Response There is no body content for the response of a successful POST query. -Disassociate Project (DEPRECATED) -================================= +Disassociate Project +==================== .. rest_method:: POST /os-networks/{network_id}/action -.. warning:: - This API is only available with ``nova-network`` which is - deprecated. It should be avoided in any new applications. - Disassociates a project from a network. Specify the ``disassociate_project`` action in the request body. @@ -295,7 +283,8 @@ these permissions through the ``policy.json`` file. Normal response codes: 202 -Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), NotImplemented(501) +Error response codes: unauthorized(401), forbidden(403), itemNotFound(404), +gone(410), notImplemented(501) Request ------- diff --git a/doc/api_samples/os-networks/network-show-resp.json b/doc/api_samples/os-networks/network-show-resp.json index 78b349501734..d6d12e41936a 100644 --- a/doc/api_samples/os-networks/network-show-resp.json +++ b/doc/api_samples/os-networks/network-show-resp.json @@ -1,36 +1,36 @@ { "network": { - "bridge": "br100", - "bridge_interface": "eth0", - "broadcast": "10.0.0.7", - "cidr": "10.0.0.0/29", + "bridge": null, + "bridge_interface": null, + "broadcast": null, + "cidr": null, "cidr_v6": null, - "created_at": "2011-08-15T06:19:19.387525", - "deleted": false, + "created_at": null, + "deleted": null, "deleted_at": null, - "dhcp_server": "10.0.0.1", - "dhcp_start": "10.0.0.3", + "dhcp_server": null, + "dhcp_start": null, "dns1": null, "dns2": null, - "enable_dhcp": true, - "gateway": "10.0.0.1", + "enable_dhcp": null, + "gateway": null, "gateway_v6": null, - "host": "nsokolov-desktop", + "host": null, "id": "20c8acc0-f747-4d71-a389-46d078ebf047", - "injected": false, - "label": "mynet_0", + "injected": null, + "label": "private", "mtu": null, - "multi_host": false, - "netmask": "255.255.255.248", + "multi_host": null, + "netmask": null, "netmask_v6": null, "priority": null, - "project_id": "6133f8b603924f45bc0c9e21f6df12fa", + "project_id": null, "rxtx_base": null, - "share_address": false, - "updated_at": "2011-08-16T09:26:13.048257", - "vlan": 100, - "vpn_private_address": "10.0.0.2", - "vpn_public_address": "127.0.0.1", - "vpn_public_port": 1000 + "share_address": null, + "updated_at": null, + "vlan": null, + "vpn_private_address": null, + "vpn_public_address": null, + "vpn_public_port": null } -} \ No newline at end of file +} diff --git a/doc/api_samples/os-networks/networks-list-resp.json b/doc/api_samples/os-networks/networks-list-resp.json index 655fcaa8ccad..886beb71708e 100644 --- a/doc/api_samples/os-networks/networks-list-resp.json +++ b/doc/api_samples/os-networks/networks-list-resp.json @@ -1,72 +1,38 @@ { "networks": [ { - "bridge": "br100", - "bridge_interface": "eth0", - "broadcast": "10.0.0.7", - "cidr": "10.0.0.0/29", + "bridge": null, + "bridge_interface": null, + "broadcast": null, + "cidr": null, "cidr_v6": null, - "created_at": "2011-08-15T06:19:19.387525", - "deleted": false, + "created_at": null, + "deleted": null, "deleted_at": null, - "dhcp_server": "10.0.0.1", - "dhcp_start": "10.0.0.3", + "dhcp_server": null, + "dhcp_start": null, "dns1": null, "dns2": null, - "enable_dhcp": true, - "gateway": "10.0.0.1", - "gateway_v6": null, - "host": "nsokolov-desktop", - "id": "20c8acc0-f747-4d71-a389-46d078ebf047", - "injected": false, - "label": "mynet_0", - "mtu": null, - "multi_host": false, - "netmask": "255.255.255.248", - "netmask_v6": null, - "priority": null, - "project_id": "6133f8b603924f45bc0c9e21f6df12fa", - "rxtx_base": null, - "share_address": false, - "updated_at": "2011-08-16T09:26:13.048257", - "vlan": 100, - "vpn_private_address": "10.0.0.2", - "vpn_public_address": "127.0.0.1", - "vpn_public_port": 1000 - }, - { - "bridge": "br101", - "bridge_interface": "eth0", - "broadcast": "10.0.0.15", - "cidr": "10.0.0.10/29", - "cidr_v6": null, - "created_at": "2011-08-15T06:19:19.885495", - "deleted": false, - "deleted_at": null, - "dhcp_server": "10.0.0.9", - "dhcp_start": "10.0.0.11", - "dns1": null, - "dns2": null, - "enable_dhcp": true, - "gateway": "10.0.0.9", + "enable_dhcp": null, + "gateway": null, "gateway_v6": null, "host": null, - "id": "20c8acc0-f747-4d71-a389-46d078ebf000", - "injected": false, - "label": "mynet_1", + "id": "20c8acc0-f747-4d71-a389-46d078ebf047", + "injected": null, + "label": "private", "mtu": null, - "multi_host": false, - "netmask": "255.255.255.248", + "multi_host": null, + "netmask": null, "netmask_v6": null, "priority": null, "project_id": null, "rxtx_base": null, - "share_address": false, + "share_address": null, "updated_at": null, - "vlan": 101, - "vpn_private_address": "10.0.0.10", + "vlan": null, + "vpn_private_address": null, "vpn_public_address": null, - "vpn_public_port": 1001 + "vpn_public_port": null } ] -} \ No newline at end of file +} diff --git a/nova/api/openstack/compute/networks.py b/nova/api/openstack/compute/networks.py index efd14253e38c..4a74256e45dd 100644 --- a/nova/api/openstack/compute/networks.py +++ b/nova/api/openstack/compute/networks.py @@ -14,15 +14,11 @@ # License for the specific language governing permissions and limitations # under the License. -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 wsgi -from nova.api import validation from nova import exception from nova.i18n import _ from nova import network @@ -92,22 +88,6 @@ 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) - @wsgi.expected_errors((404, 501)) - @wsgi.action("disassociate") - def _disassociate_host_and_project(self, req, id, body): - context = req.environ['nova.context'] - context.can(net_policies.BASE_POLICY_NAME) - - try: - self.network_api.associate(context, id, host=None, project=None) - except exception.NetworkNotFound: - msg = _("Network not found") - raise exc.HTTPNotFound(explanation=msg) - except NotImplementedError: - common.raise_feature_not_supported() - @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.expected_errors(404) def show(self, req, id): @@ -121,63 +101,19 @@ 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) - @wsgi.expected_errors((404, 409)) + @wsgi.expected_errors(410) + @wsgi.action("disassociate") + def _disassociate_host_and_project(self, req, id, body): + raise exc.HTTPGone() + + @wsgi.expected_errors(410) def delete(self, req, id): - context = req.environ['nova.context'] - context.can(net_policies.BASE_POLICY_NAME) + raise exc.HTTPGone() - try: - self.network_api.delete(context, id) - except exception.NetworkInUse as e: - raise exc.HTTPConflict(explanation=e.format_message()) - except exception.NetworkNotFound: - msg = _("Network not found") - raise exc.HTTPNotFound(explanation=msg) - - @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) - @wsgi.expected_errors((400, 409, 501)) - @validation.schema(schema.create) + @wsgi.expected_errors(410) def create(self, req, body): - context = req.environ['nova.context'] - context.can(net_policies.BASE_POLICY_NAME) + raise exc.HTTPGone() - params = body["network"] - - cidr = params.get("cidr") or params.get("cidr_v6") - - params["num_networks"] = 1 - params["network_size"] = netaddr.IPNetwork(cidr).size - - try: - network = self.network_api.create(context, **params)[0] - except (exception.InvalidCidr, - exception.InvalidIntValue, - exception.InvalidAddress, - exception.NetworkNotCreated) as ex: - raise exc.HTTPBadRequest(explanation=ex.format_message) - except (exception.CidrConflict, - exception.DuplicateVlan) as ex: - 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) - @wsgi.expected_errors((400, 501)) - @validation.schema(schema.add_network_to_project) + @wsgi.expected_errors(410) def add(self, req, body): - context = req.environ['nova.context'] - context.can(net_policies.BASE_POLICY_NAME) - - network_id = body['id'] - project_id = context.project_id - - try: - self.network_api.add_network_to_project( - context, project_id, network_id) - except NotImplementedError: - common.raise_feature_not_supported() - except (exception.NoMoreNetworks, - exception.NetworkNotFoundForUUID) as e: - raise exc.HTTPBadRequest(explanation=e.format_message()) + raise exc.HTTPGone() diff --git a/nova/api/openstack/compute/networks_associate.py b/nova/api/openstack/compute/networks_associate.py index b4f0e9a83b76..e49b1ae9e403 100644 --- a/nova/api/openstack/compute/networks_associate.py +++ b/nova/api/openstack/compute/networks_associate.py @@ -12,70 +12,23 @@ 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 wsgi -from nova.api import validation -from nova import exception -from nova.i18n import _ -from nova import network -from nova.policies import networks_associate as na_policies class NetworkAssociateActionController(wsgi.Controller): """Network Association API Controller.""" - def __init__(self, network_api=None): - super(NetworkAssociateActionController, self).__init__() - # TODO(stephenfin): 'network_api' is only being passed for use by tests - 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) - @wsgi.expected_errors((404, 501)) + @wsgi.expected_errors(410) def _disassociate_host_only(self, req, id, body): - context = req.environ['nova.context'] - context.can(na_policies.BASE_POLICY_NAME) - try: - self.network_api.associate(context, id, host=None) - except exception.NetworkNotFound: - msg = _("Network not found") - raise exc.HTTPNotFound(explanation=msg) - except NotImplementedError: - common.raise_feature_not_supported() + raise exc.HTTPGone() - @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.action("disassociate_project") - @wsgi.response(202) - @wsgi.expected_errors((404, 501)) + @wsgi.expected_errors(410) def _disassociate_project_only(self, req, id, body): - context = req.environ['nova.context'] - context.can(na_policies.BASE_POLICY_NAME) - try: - self.network_api.associate(context, id, project=None) - except exception.NetworkNotFound: - msg = _("Network not found") - raise exc.HTTPNotFound(explanation=msg) - except NotImplementedError: - common.raise_feature_not_supported() + raise exc.HTTPGone() - @wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.action("associate_host") - @wsgi.response(202) - @wsgi.expected_errors((404, 501)) - @validation.schema(networks_associate.associate_host) + @wsgi.expected_errors(410) def _associate_host(self, req, id, body): - context = req.environ['nova.context'] - context.can(na_policies.BASE_POLICY_NAME) - - try: - self.network_api.associate(context, id, - host=body['associate_host']) - except exception.NetworkNotFound: - msg = _("Network not found") - raise exc.HTTPNotFound(explanation=msg) - except NotImplementedError: - common.raise_feature_not_supported() + raise exc.HTTPGone() diff --git a/nova/api/openstack/compute/rest_api_version_history.rst b/nova/api/openstack/compute/rest_api_version_history.rst index 37194b74c928..0f815c8e9bed 100644 --- a/nova/api/openstack/compute/rest_api_version_history.rst +++ b/nova/api/openstack/compute/rest_api_version_history.rst @@ -435,6 +435,12 @@ API endpoints as below:: 21.0.0 (Ussuri) release. On deployments newer than this, the APIs will return HTTP 410 (Gone) regadless of the requested microversion. +.. versionchanged:: 21.0.0 + + The ``os-networks`` API was partially removed in the 21.0.0 (Ussuri) + release. On deployments newer than this, some endpoints of the API will + return HTTP 410 (Gone) regadless of the requested microversion. + 2.37 ---- diff --git a/nova/api/openstack/compute/schemas/networks.py b/nova/api/openstack/compute/schemas/networks.py deleted file mode 100644 index 2fd687094391..000000000000 --- a/nova/api/openstack/compute/schemas/networks.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2015 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from nova.api.validation import parameter_types - - -create = { - 'type': 'object', - 'properties': { - 'network': { - 'type': 'object', - 'properties': { - 'label': { - 'type': 'string', 'maxLength': 255 - }, - 'ipam': parameter_types.boolean, - 'cidr': parameter_types.cidr, - 'cidr_v6': parameter_types.cidr, - 'project_id': parameter_types.project_id, - 'multi_host': parameter_types.boolean, - 'gateway': parameter_types.ipv4, - 'gateway_v6': parameter_types.ipv6, - 'bridge': { - 'type': 'string', - }, - 'bridge_interface': { - 'type': 'string', - }, - # NOTE: In _extract_subnets(), dns1, dns2 dhcp_server are - # used only for IPv4, not IPv6. - 'dns1': parameter_types.ipv4, - 'dns2': parameter_types.ipv4, - 'dhcp_server': parameter_types.ipv4, - - 'fixed_cidr': parameter_types.cidr, - 'allowed_start': parameter_types.ip_address, - 'allowed_end': parameter_types.ip_address, - 'enable_dhcp': parameter_types.boolean, - 'share_address': parameter_types.boolean, - 'mtu': parameter_types.positive_integer_with_empty_str, - 'vlan': parameter_types.positive_integer_with_empty_str, - 'vlan_start': parameter_types.positive_integer_with_empty_str, - 'vpn_start': { - 'type': 'string', - }, - }, - 'required': ['label'], - 'oneOf': [ - {'required': ['cidr']}, - {'required': ['cidr_v6']} - ], - 'additionalProperties': False, - }, - }, - 'required': ['network'], - 'additionalProperties': False, -} - -add_network_to_project = { - 'type': 'object', - 'properties': { - 'id': {'type': ['string', 'null']} - }, - 'required': ['id'], - 'additionalProperties': False -} diff --git a/nova/api/openstack/compute/schemas/networks_associate.py b/nova/api/openstack/compute/schemas/networks_associate.py deleted file mode 100644 index 73fc6bf7d20c..000000000000 --- a/nova/api/openstack/compute/schemas/networks_associate.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2015 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from nova.api.validation import parameter_types - -associate_host = { - 'type': 'object', - 'properties': { - 'associate_host': parameter_types.hostname - }, - 'required': ['associate_host'], - 'additionalProperties': False -} diff --git a/nova/policies/__init__.py b/nova/policies/__init__.py index de2deb86a4c5..7126470256e2 100644 --- a/nova/policies/__init__.py +++ b/nova/policies/__init__.py @@ -47,7 +47,6 @@ from nova.policies import migrate_server from nova.policies import migrations from nova.policies import multinic from nova.policies import networks -from nova.policies import networks_associate from nova.policies import pause_server from nova.policies import quota_class_sets from nova.policies import quota_sets @@ -109,7 +108,6 @@ def list_rules(): migrations.list_rules(), multinic.list_rules(), networks.list_rules(), - networks_associate.list_rules(), pause_server.list_rules(), quota_class_sets.list_rules(), quota_sets.list_rules(), diff --git a/nova/policies/networks.py b/nova/policies/networks.py index 812af1a63dea..562858e71821 100644 --- a/nova/policies/networks.py +++ b/nova/policies/networks.py @@ -18,36 +18,10 @@ from oslo_policy import policy from nova.policies import base -BASE_POLICY_NAME = 'os_compute_api:os-networks' POLICY_ROOT = 'os_compute_api:os-networks:%s' networks_policies = [ - policy.DocumentedRuleDefault( - BASE_POLICY_NAME, - base.RULE_ADMIN_API, - """Create and delete a network, add and disassociate a network -from a project. - -These APIs are only available with nova-network which is deprecated.""", - [ - { - 'method': 'POST', - 'path': '/os-networks' - }, - { - 'method': 'POST', - 'path': '/os-networks/add' - }, - { - 'method': 'DELETE', - 'path': '/os-networks/{network_id}' - }, - { - 'method': 'POST', - 'path': '/os-networks/{network_id}/action (disassociate)' - } - ]), policy.DocumentedRuleDefault( POLICY_ROOT % 'view', base.RULE_ADMIN_OR_OWNER, diff --git a/nova/policies/networks_associate.py b/nova/policies/networks_associate.py deleted file mode 100644 index 0cff987d6da3..000000000000 --- a/nova/policies/networks_associate.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2016 Cloudbase Solutions Srl -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_policy import policy - -from nova.policies import base - - -BASE_POLICY_NAME = 'os_compute_api:os-networks-associate' - - -networks_associate_policies = [ - policy.DocumentedRuleDefault( - BASE_POLICY_NAME, - base.RULE_ADMIN_API, - """Associate or disassociate a network from a host or project. - -These APIs are only available with nova-network which is deprecated.""", - [ - { - 'method': 'POST', - 'path': '/os-networks/{network_id}/action (disassociate_host)' - }, - { - 'method': 'POST', - 'path': '/os-networks/{network_id}/action' - ' (disassociate_project)' - }, - { - 'method': 'POST', - 'path': '/os-networks/{network_id}/action (associate_host)' - } - ]), -] - - -def list_rules(): - return networks_associate_policies diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-associate-host-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-associate-host-req.json.tpl deleted file mode 100644 index 762e8817518e..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-associate-host-req.json.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{ - "associate_host": "%(host)s" -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-host-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-host-req.json.tpl deleted file mode 100644 index 46f69b3e8190..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-host-req.json.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disassociate_host": null -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-project-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-project-req.json.tpl deleted file mode 100644 index 63b6eb683997..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-project-req.json.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disassociate_project": null -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-req.json.tpl deleted file mode 100644 index 2e09d15a60a9..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks-associate/network-disassociate-req.json.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disassociate": null -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-add-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-add-req.json.tpl deleted file mode 100644 index aca6770b3b20..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-add-req.json.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "1" -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-req.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-req.json.tpl deleted file mode 100644 index 18515bd6c494..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-req.json.tpl +++ /dev/null @@ -1,12 +0,0 @@ -{ - "network": { - "label": "new net 111", - "cidr": "10.20.105.0/24", - "mtu": 9000, - "dhcp_server": "10.20.105.2", - "enable_dhcp": false, - "share_address": true, - "allowed_start": "10.20.105.10", - "allowed_end": "10.20.105.200" - } -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-resp.json.tpl deleted file mode 100644 index 5cf155b13fea..000000000000 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-create-resp.json.tpl +++ /dev/null @@ -1,36 +0,0 @@ -{ - "network": { - "bridge": null, - "vpn_public_port": null, - "dhcp_start": "%(ip)s", - "bridge_interface": null, - "updated_at": null, - "id": "%(id)s", - "cidr_v6": null, - "deleted_at": null, - "gateway": "%(ip)s", - "rxtx_base": null, - "label": "new net 111", - "priority": null, - "project_id": null, - "vpn_private_address": null, - "deleted": null, - "vlan": null, - "broadcast": "%(ip)s", - "netmask": "%(ip)s", - "injected": null, - "cidr": "10.20.105.0/24", - "vpn_public_address": null, - "multi_host": null, - "dns2": null, - "created_at": null, - "host": null, - "gateway_v6": null, - "netmask_v6": null, - "dns1": null, - "mtu": 9000, - "dhcp_server": "10.20.105.2", - "enable_dhcp": false, - "share_address": true - } -} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-show-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-show-resp.json.tpl index 23b463762ef5..39d0c3146dbe 100644 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-show-resp.json.tpl +++ b/nova/tests/functional/api_sample_tests/api_samples/os-networks/network-show-resp.json.tpl @@ -1,37 +1,37 @@ { "network": { - "bridge": "br100", - "bridge_interface": "eth0", - "broadcast": "%(ip)s", - "cidr": "10.0.0.0/29", + "bridge": null, + "bridge_interface": null, + "broadcast": null, + "cidr": null, "cidr_v6": null, - "created_at": "%(strtime)s", - "deleted": false, + "created_at": null, + "deleted": null, "deleted_at": null, - "dhcp_start": "%(ip)s", + "dhcp_start": null, "dns1": null, "dns2": null, - "gateway": "%(ip)s", + "gateway": null, "gateway_v6": null, - "host": "nsokolov-desktop", + "host": null, "id": "%(id)s", - "injected": false, - "label": "mynet_0", - "multi_host": false, - "netmask": "%(ip)s", + "injected": null, + "label": "private", + "multi_host": null, + "netmask": null, "netmask_v6": null, "priority": null, - "project_id": "6133f8b603924f45bc0c9e21f6df12fa", + "project_id": null, "rxtx_base": null, - "updated_at": "%(strtime)s", - "vlan": 100, - "vpn_private_address": "%(ip)s", - "vpn_public_address": "%(ip)s", - "vpn_public_port": 1000, + "updated_at": null, + "vlan": null, + "vpn_private_address": null, + "vpn_public_address": null, + "vpn_public_port": null, "mtu": null, - "dhcp_server": "%(ip)s", - "enable_dhcp": true, - "share_address": false + "dhcp_server": null, + "enable_dhcp": null, + "share_address": null } } diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-networks/networks-list-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-networks/networks-list-resp.json.tpl index b728e26bf1b7..37bd56f1ed34 100644 --- a/nova/tests/functional/api_sample_tests/api_samples/os-networks/networks-list-resp.json.tpl +++ b/nova/tests/functional/api_sample_tests/api_samples/os-networks/networks-list-resp.json.tpl @@ -1,72 +1,38 @@ { "networks": [ { - "bridge": "br100", - "bridge_interface": "eth0", - "broadcast": "%(ip)s", - "cidr": "10.0.0.0/29", + "bridge": null, + "bridge_interface": null, + "broadcast": null, + "cidr": null, "cidr_v6": null, - "created_at": "%(strtime)s", - "deleted": false, + "created_at": null, + "deleted": null, "deleted_at": null, - "dhcp_start": "%(ip)s", + "dhcp_start": null, "dns1": null, "dns2": null, - "gateway": "%(ip)s", - "gateway_v6": null, - "host": "nsokolov-desktop", - "id": "%(id)s", - "injected": false, - "label": "mynet_0", - "multi_host": false, - "netmask": "%(ip)s", - "netmask_v6": null, - "priority": null, - "project_id": "6133f8b603924f45bc0c9e21f6df12fa", - "rxtx_base": null, - "updated_at": "%(strtime)s", - "vlan": 100, - "vpn_private_address": "%(ip)s", - "vpn_public_address": "%(ip)s", - "vpn_public_port": 1000, - "mtu": null, - "dhcp_server": "%(ip)s", - "enable_dhcp": true, - "share_address": false - }, - { - "bridge": "br101", - "bridge_interface": "eth0", - "broadcast": "%(ip)s", - "cidr": "10.0.0.10/29", - "cidr_v6": null, - "created_at": "%(strtime)s", - "deleted": false, - "deleted_at": null, - "dhcp_start": "%(ip)s", - "dns1": null, - "dns2": null, - "gateway": "%(ip)s", + "gateway": null, "gateway_v6": null, "host": null, "id": "%(id)s", - "injected": false, - "label": "mynet_1", - "multi_host": false, - "netmask": "%(ip)s", + "injected": null, + "label": "private", + "multi_host": null, + "netmask": null, "netmask_v6": null, "priority": null, "project_id": null, "rxtx_base": null, "updated_at": null, - "vlan": 101, - "vpn_private_address": "%(ip)s", + "vlan": null, + "vpn_private_address": null, "vpn_public_address": null, - "vpn_public_port": 1001, + "vpn_public_port": null, "mtu": null, - "dhcp_server": "%(ip)s", - "enable_dhcp": true, - "share_address": false + "dhcp_server": null, + "enable_dhcp": null, + "share_address": null } ] } diff --git a/nova/tests/functional/api_sample_tests/test_networks.py b/nova/tests/functional/api_sample_tests/test_networks.py index 1a47009686e1..37dec9b3fe7a 100644 --- a/nova/tests/functional/api_sample_tests/test_networks.py +++ b/nova/tests/functional/api_sample_tests/test_networks.py @@ -16,91 +16,38 @@ import mock from nova import exception +from nova.tests import fixtures as nova_fixtures from nova.tests.functional.api_sample_tests import api_sample_base -from nova.tests.unit.api.openstack.compute import test_networks -def _fixtures_passthrough(method_name): - # This compensates for how fixtures 3.x handles the signatures of - # MonkeyPatched functions vs fixtures < 3.x. In fixtures 3 if a bound - # method is patched in for a bound method then both objects will be passed - # in when called. This means the patch method should have the signature of - # (self, targetself, *args, **kwargs). However that will not work for - # fixtures < 3. This method captures self from the call point and discards - # it since it's not needed. - fake_network_api = test_networks.FakeNetworkAPI() - method = getattr(fake_network_api, method_name) - - def call(self, *args, **kwargs): - # self is the nova.network.api.API object that has been patched - # method is bound to FakeNetworkAPI so that will be passed in as self - return method(*args, **kwargs) - - return call - - -# TODO(stephenfin): Remove the parts of this test that are nova-network only class NetworksJsonTests(api_sample_base.ApiSampleTestBaseV21): - USE_NEUTRON = False # partially nova-net only ADMIN_API = True - sample_dir = "os-networks" + sample_dir = 'os-networks' - def setUp(self): - super(NetworksJsonTests, self).setUp() - self.stub_out("nova.network.api.API.get_all", - _fixtures_passthrough('get_all')) - self.stub_out("nova.network.api.API.get", - _fixtures_passthrough('get')) - self.stub_out("nova.network.api.API.associate", - _fixtures_passthrough('associate')) - self.stub_out("nova.network.api.API.delete", - _fixtures_passthrough('delete')) - self.stub_out("nova.network.api.API.create", - _fixtures_passthrough('create')) - self.stub_out("nova.network.api.API.add_network_to_project", - _fixtures_passthrough('add_network_to_project')) - - # TODO(stephenfin): Rework this to work with neutron def test_network_list(self): response = self._do_get('os-networks') self._verify_response('networks-list-resp', {}, response, 200) - # TODO(stephenfin): Rework this to work with neutron def test_network_show(self): - uuid = test_networks.FAKE_NETWORKS[0]['uuid'] + uuid = nova_fixtures.NeutronFixture.network_1['id'] response = self._do_get('os-networks/%s' % uuid) self._verify_response('network-show-resp', {}, response, 200) - # TODO(stephenfin): Rework this to work with neutron - @mock.patch('nova.network.api.API.get', side_effect=exception.Unauthorized) + @mock.patch('nova.network.neutronv2.api.API.get', + side_effect=exception.Unauthorized) def test_network_show_token_expired(self, mock_get): - uuid = test_networks.FAKE_NETWORKS[0]['uuid'] + uuid = nova_fixtures.NeutronFixture.network_1['id'] response = self._do_get('os-networks/%s' % uuid) self.assertEqual(401, response.status_code) - # TODO(stephenfin): Remove this API since it's nova-network only - @mock.patch('nova.network.api.API.create', - side_effect=exception.Forbidden) - def test_network_create_forbidden(self, mock_create): - response = self._do_post("os-networks", - 'network-create-req', {}) - self.assertEqual(403, response.status_code) - - # TODO(stephenfin): Remove this API since it's nova-network only def test_network_create(self): - response = self._do_post("os-networks", - 'network-create-req', {}) - self._verify_response('network-create-resp', {}, response, 200) + self.api.api_post('os-networks', {}, + check_response_status=[410]) - # TODO(stephenfin): Remove this API since it's nova-network only def test_network_add(self): - response = self._do_post("os-networks/add", - 'network-add-req', {}) - self.assertEqual(202, response.status_code) - self.assertEqual("", response.text) + self.api.api_post('os-networks/add', {}, + check_response_status=[410]) - # TODO(stephenfin): Remove this API since it's nova-network only def test_network_delete(self): - response = self._do_delete('os-networks/always_delete') - self.assertEqual(202, response.status_code) - self.assertEqual("", response.text) + self.api.api_delete('os-networks/always-delete', + check_response_status=[410]) diff --git a/nova/tests/functional/api_sample_tests/test_networks_associate.py b/nova/tests/functional/api_sample_tests/test_networks_associate.py index ddc7263f2742..0e40af48d718 100644 --- a/nova/tests/functional/api_sample_tests/test_networks_associate.py +++ b/nova/tests/functional/api_sample_tests/test_networks_associate.py @@ -16,48 +16,25 @@ from nova.tests.functional.api_sample_tests import api_sample_base -# TODO(stephenfin): Remove this API since it's nova-network only class NetworksAssociateJsonTests(api_sample_base.ApiSampleTestBaseV21): - USE_NEUTRON = False # nova-net only ADMIN_API = True - sample_dir = "os-networks-associate" - - _sentinel = object() - - def setUp(self): - super(NetworksAssociateJsonTests, self).setUp() - - def fake_associate(self, context, network_id, - host=NetworksAssociateJsonTests._sentinel, - project=NetworksAssociateJsonTests._sentinel): - return True - - self.stub_out("nova.network.api.API.associate", fake_associate) def test_disassociate(self): - response = self._do_post('os-networks/1/action', - 'network-disassociate-req', - {}) - self.assertEqual(202, response.status_code) - self.assertEqual("", response.text) + self.api.api_post('os-networks/1/action', + {'disassociate': None}, + check_response_status=[410]) def test_disassociate_host(self): - response = self._do_post('os-networks/1/action', - 'network-disassociate-host-req', - {}) - self.assertEqual(202, response.status_code) - self.assertEqual("", response.text) + self.api.api_post('os-networks/1/action', + {'disassociate_host': None}, + check_response_status=[410]) def test_disassociate_project(self): - response = self._do_post('os-networks/1/action', - 'network-disassociate-project-req', - {}) - self.assertEqual(202, response.status_code) - self.assertEqual("", response.text) + self.api.api_post('os-networks/1/action', + {'disassociate_project': None}, + check_response_status=[410]) def test_associate_host(self): - response = self._do_post('os-networks/1/action', - 'network-associate-host-req', - {"host": "testHost"}) - self.assertEqual(202, response.status_code) - self.assertEqual("", response.text) + self.api.api_post('os-networks/1/action', + {'associate_host': 'foo'}, + check_response_status=[410]) diff --git a/nova/tests/unit/api/openstack/compute/test_networks.py b/nova/tests/unit/api/openstack/compute/test_networks.py index 0917e1624849..888b2c76d120 100644 --- a/nova/tests/unit/api/openstack/compute/test_networks.py +++ b/nova/tests/unit/api/openstack/compute/test_networks.py @@ -16,21 +16,15 @@ import copy import datetime -import math import iso8601 -import mock -import netaddr from oslo_config import cfg from oslo_utils.fixture import uuidsentinel as uuids import webob from nova.api.openstack.compute import networks as networks_v21 -from nova.api.openstack.compute import networks_associate \ - as networks_associate_v21 import nova.context from nova import exception -from nova.network import manager from nova.network.neutronv2 import api as neutron from nova import objects from nova import test @@ -121,48 +115,6 @@ class FakeNetworkAPI(object): def __init__(self): self.networks = copy.deepcopy(FAKE_NETWORKS) - def delete(self, context, network_id): - if network_id == 'always_delete': - return True - if network_id == -1: - raise exception.NetworkInUse(network_id=network_id) - for i, network in enumerate(self.networks): - if network['id'] == network_id: - del self.networks[0] - return True - raise exception.NetworkNotFoundForUUID(uuid=network_id) - - def disassociate(self, context, network_uuid): - for network in self.networks: - if network.get('uuid') == network_uuid: - network['project_id'] = None - return True - raise exception.NetworkNotFound(network_id=network_uuid) - - def associate(self, context, network_uuid, host=_sentinel, - project=_sentinel): - for network in self.networks: - if network.get('uuid') == network_uuid: - if host is not FakeNetworkAPI._sentinel: - network['host'] = host - if project is not FakeNetworkAPI._sentinel: - network['project_id'] = project - return True - raise exception.NetworkNotFound(network_id=network_uuid) - - def add_network_to_project(self, context, - project_id, network_uuid=None): - if network_uuid: - for network in self.networks: - if network.get('project_id', None) is None: - network['project_id'] = project_id - return - return - for network in self.networks: - if network.get('uuid') == network_uuid: - network['project_id'] = project_id - return - def get_all(self, context): return self._fake_db_network_get_all(context, project_only=True) @@ -199,146 +151,13 @@ class FakeNetworkAPI(object): network) raise exception.NetworkNotFound(network_id=network_id) - def create(self, context, **kwargs): - subnet_bits = int(math.ceil(math.log(kwargs.get( - 'network_size', CONF.network_size), 2))) - fixed_net_v4 = netaddr.IPNetwork(kwargs['cidr']) - prefixlen_v4 = 32 - subnet_bits - subnets_v4 = list(fixed_net_v4.subnet( - prefixlen_v4, - count=kwargs.get('num_networks', CONF.num_networks))) - new_networks = [] - new_id = max((net['id'] for net in self.networks)) - for index, subnet_v4 in enumerate(subnets_v4): - new_id += 1 - net = {'id': new_id, 'uuid': uuids.fake} - - net['cidr'] = str(subnet_v4) - net['netmask'] = str(subnet_v4.netmask) - net['gateway'] = kwargs.get('gateway') or str(subnet_v4[1]) - net['broadcast'] = str(subnet_v4.broadcast) - net['dhcp_start'] = str(subnet_v4[2]) - - for key in FAKE_NETWORKS[0]: - net.setdefault(key, kwargs.get(key)) - new_networks.append(net) - self.networks += new_networks - return new_networks - - -# NOTE(vish): tests that network create Exceptions actually return -# the proper error responses -class NetworkCreateExceptionsTestV21(test.TestCase): - validation_error = exception.ValidationError - - class PassthroughAPI(object): - def __init__(self): - self.network_manager = manager.FlatDHCPManager() - - def create(self, *args, **kwargs): - if kwargs['label'] == 'fail_NetworkNotCreated': - raise exception.NetworkNotCreated(req='fake_fail') - return self.network_manager.create_networks(*args, **kwargs) - - def setUp(self): - super(NetworkCreateExceptionsTestV21, self).setUp() - self._setup() - fakes.stub_out_networking(self) - self.new_network = copy.deepcopy(NEW_NETWORK) - - def _setup(self): - self.req = fakes.HTTPRequest.blank('') - self.controller = networks_v21.NetworkController(self.PassthroughAPI()) - - def test_network_create_bad_vlan(self): - self.new_network['network']['vlan_start'] = 'foo' - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_no_cidr(self): - del self.new_network['network']['cidr'] - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_no_label(self): - del self.new_network['network']['label'] - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_label_too_long(self): - self.new_network['network']['label'] = "x" * 256 - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_invalid_fixed_cidr(self): - self.new_network['network']['fixed_cidr'] = 'foo' - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_invalid_start(self): - self.new_network['network']['allowed_start'] = 'foo' - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_bad_cidr(self): - self.new_network['network']['cidr'] = '128.0.0.0/900' - self.assertRaises(self.validation_error, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_handle_network_not_created(self): - self.new_network['network']['label'] = 'fail_NetworkNotCreated' - self.assertRaises(webob.exc.HTTPBadRequest, - self.controller.create, self.req, - body=self.new_network) - - @mock.patch.object(objects.NetworkList, 'get_all') - def test_network_create_cidr_conflict(self, mock_get_all): - def fake_get_all(context): - ret = objects.NetworkList(context=context, objects=[]) - net = objects.Network(cidr='10.0.0.0/23') - ret.objects.append(net) - return ret - - mock_get_all.side_effect = fake_get_all - - self.new_network['network']['cidr'] = '10.0.0.0/24' - self.assertRaises(webob.exc.HTTPConflict, - self.controller.create, self.req, - body=self.new_network) - - def test_network_create_vlan_conflict(self): - - @staticmethod - def get_all(context): - ret = objects.NetworkList(context=context, objects=[]) - net = objects.Network(cidr='10.0.0.0/24', vlan=100) - ret.objects.append(net) - return ret - - def fake_create(context): - raise exception.DuplicateVlan(vlan=100) - - self.stub_out('nova.objects.NetworkList.get_all', get_all) - self.stub_out('nova.objects.Network.create', fake_create) - - self.new_network['network']['cidr'] = '20.0.0.0/24' - self.assertRaises(webob.exc.HTTPConflict, - self.controller.create, self.req, - body=self.new_network) - class NetworksTestV21(test.NoDBTestCase): validation_error = exception.ValidationError def setUp(self): super(NetworksTestV21, self).setUp() + # TODO(stephenfin): Consider using then NeutronFixture here self.fake_network_api = FakeNetworkAPI() self._setup() fakes.stub_out_networking(self) @@ -370,18 +189,6 @@ class NetworksTestV21(test.NoDBTestCase): res_dict = self.controller.index(self.non_admin_req) self.assertEqual(res_dict, {'networks': []}) - project_id = self.req.environ["nova.context"].project_id - cxt = self.req.environ["nova.context"] - uuid = FAKE_NETWORKS[0]['uuid'] - self.fake_network_api.associate(context=cxt, - network_uuid=uuid, - project=project_id) - res_dict = self.controller.index(self.non_admin_req) - expected = [copy.deepcopy(FAKE_USER_NETWORKS[0])] - for network in expected: - self.network_uuid_to_id(network) - self.assertEqual({'networks': expected}, res_dict) - def test_network_list_all_as_admin(self): res_dict = self.controller.index(self.admin_req) expected = copy.deepcopy(FAKE_NETWORKS) @@ -389,19 +196,6 @@ class NetworksTestV21(test.NoDBTestCase): self.network_uuid_to_id(network) self.assertEqual({'networks': expected}, res_dict) - def test_network_disassociate(self): - uuid = FAKE_NETWORKS[0]['uuid'] - 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']) - - def test_network_disassociate_not_found(self): - self.assertRaises(webob.exc.HTTPNotFound, - self.controller._disassociate_host_and_project, - self.req, 100, {'disassociate': None}) - def test_network_get_as_user(self): uuid = FAKE_USER_NETWORKS[0]['uuid'] res_dict = self.controller.show(self.non_admin_req, uuid) @@ -420,200 +214,6 @@ class NetworksTestV21(test.NoDBTestCase): self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, self.req, 100) - def test_network_delete(self): - 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, - self.controller.delete, self.req, 100) - - def test_network_delete_in_use(self): - self.assertRaises(webob.exc.HTTPConflict, - self.controller.delete, self.req, -1) - - def test_network_add(self): - uuid = FAKE_NETWORKS[1]['uuid'] - 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'], - fakes.FAKE_PROJECT_ID) - - @mock.patch('nova.tests.unit.api.openstack.compute.test_networks.' - 'FakeNetworkAPI.add_network_to_project', - side_effect=exception.NoMoreNetworks) - def test_network_add_no_more_networks_fail(self, mock_add): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.add, - self.req, body={'id': uuid}) - - @mock.patch('nova.tests.unit.api.openstack.compute.test_networks.' - 'FakeNetworkAPI.add_network_to_project', - side_effect=exception. - NetworkNotFoundForUUID(uuid=fakes.FAKE_PROJECT_ID)) - def test_network_add_network_not_found_networks_fail(self, mock_add): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.add, - self.req, body={'id': uuid}) - - def test_network_add_network_without_body(self): - self.assertRaises(self.validation_error, self.controller.add, - self.req, - body=None) - - def test_network_add_network_with_invalid_id(self): - self.assertRaises(exception.ValidationError, self.controller.add, - self.req, - body={'id': 123}) - - def test_network_add_network_with_extra_arg(self): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(exception.ValidationError, self.controller.add, - self.req, - body={'id': uuid, - 'extra_arg': 123}) - - def test_network_add_network_with_none_id(self): - 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) - self.assertIn('network', res_dict) - uuid = res_dict['network']['id'] - res_dict = self.controller.show(self.req, uuid) - self.assertTrue(res_dict['network']['label']. - startswith(NEW_NETWORK['network']['label'])) - - def test_network_create_large(self): - self.new_network['network']['cidr'] = '128.0.0.0/4' - res_dict = self.controller.create(self.req, body=self.new_network) - self.assertEqual(res_dict['network']['cidr'], - self.new_network['network']['cidr']) - - def test_network_neutron_disassociate_not_implemented(self): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(webob.exc.HTTPNotImplemented, - self.neutron_ctrl._disassociate_host_and_project, - self.req, uuid, {'disassociate': None}) - - -class NetworksAssociateTestV21(test.NoDBTestCase): - - def setUp(self): - super(NetworksAssociateTestV21, self).setUp() - self.fake_network_api = FakeNetworkAPI() - self._setup() - fakes.stub_out_networking(self) - self.admin_req = fakes.HTTPRequest.blank('', use_admin_context=True) - - def _setup(self): - self.controller = networks_v21.NetworkController(self.fake_network_api) - self.associate_controller = networks_associate_v21\ - .NetworkAssociateActionController(self.fake_network_api) - self.neutron_assoc_ctrl = ( - networks_associate_v21.NetworkAssociateActionController( - neutron.API())) - self.req = fakes.HTTPRequest.blank('') - - def _check_status(self, res, method, code): - self.assertEqual(method.wsgi_code, code) - - def test_network_disassociate_host_only(self): - uuid = FAKE_NETWORKS[0]['uuid'] - disassociate = self.associate_controller._disassociate_host_only - res = disassociate( - self.req, uuid, {'disassociate_host': None}) - self._check_status(res, - 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'] - 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'] - 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[1]['project_id']) - 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, delete.wsgi_code) - - def test_network_associate_project_delete_fail(self): - uuid = FAKE_NETWORKS[0]['uuid'] - req = fakes.HTTPRequest.blank( - '/v2/%s/os-networks/%s/action' % (fakes.FAKE_PROJECT_ID, uuid)) - self.assertRaises(webob.exc.HTTPConflict, - self.controller.delete, req, -1) - - def test_network_associate_with_host(self): - uuid = FAKE_NETWORKS[1]['uuid'] - 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') - - def test_network_neutron_associate_not_implemented(self): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(webob.exc.HTTPNotImplemented, - self.neutron_assoc_ctrl._associate_host, - self.req, uuid, body={'associate_host': "TestHost"}) - - def _test_network_neutron_associate_host_validation_failed(self, body): - uuid = FAKE_NETWORKS[1]['uuid'] - - self.assertRaises(exception.ValidationError, - self.associate_controller._associate_host, - self.req, uuid, body=body) - - def test_network_neutron_associate_host_non_string(self): - self._test_network_neutron_associate_host_validation_failed( - {'associate_host': 123}) - - def test_network_neutron_associate_host_empty_body(self): - self._test_network_neutron_associate_host_validation_failed({}) - - def test_network_neutron_associate_bad_associate_host_key(self): - self._test_network_neutron_associate_host_validation_failed( - {'badassociate_host': "TestHost"}) - - def test_network_neutron_associate_host_extra_arg(self): - self._test_network_neutron_associate_host_validation_failed( - {'associate_host': "TestHost", - 'extra_arg': "extra_arg"}) - - def test_network_neutron_disassociate_project_not_implemented(self): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(webob.exc.HTTPNotImplemented, - self.neutron_assoc_ctrl._disassociate_project_only, - self.req, uuid, {'disassociate_project': None}) - - def test_network_neutron_disassociate_host_not_implemented(self): - uuid = FAKE_NETWORKS[1]['uuid'] - self.assertRaises(webob.exc.HTTPNotImplemented, - self.neutron_assoc_ctrl._disassociate_host_only, - self.req, uuid, {'disassociate_host': None}) - class NetworksEnforcementV21(test.NoDBTestCase): @@ -642,90 +242,6 @@ class NetworksEnforcementV21(test.NoDBTestCase): "Policy doesn't allow %s to be performed." % rule_name, exc.format_message()) - def test_create_policy_failed(self): - rule_name = 'os_compute_api:os-networks' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller.create, self.req, body=NEW_NETWORK) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - - def test_delete_policy_failed(self): - rule_name = 'os_compute_api:os-networks' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller.delete, self.req, fakes.FAKE_UUID) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - - def test_add_policy_failed(self): - rule_name = 'os_compute_api:os-networks' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller.add, self.req, - body={'id': fakes.FAKE_UUID}) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - - def test_disassociate_policy_failed(self): - rule_name = 'os_compute_api:os-networks' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller._disassociate_host_and_project, - self.req, fakes.FAKE_UUID, body={'network': {}}) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - - -class NetworksAssociateEnforcementV21(test.NoDBTestCase): - - def setUp(self): - super(NetworksAssociateEnforcementV21, self).setUp() - self.controller = (networks_associate_v21. - NetworkAssociateActionController()) - self.req = fakes.HTTPRequest.blank('') - - def test_disassociate_host_policy_failed(self): - rule_name = 'os_compute_api:os-networks-associate' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller._disassociate_host_only, - self.req, fakes.FAKE_UUID, body={'disassociate_host': {}}) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - - def test_disassociate_project_only_policy_failed(self): - rule_name = 'os_compute_api:os-networks-associate' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller._disassociate_project_only, - self.req, fakes.FAKE_UUID, body={'disassociate_project': {}}) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - - def test_disassociate_host_only_policy_failed(self): - rule_name = 'os_compute_api:os-networks-associate' - self.policy.set_rules({rule_name: "project:non_fake"}) - exc = self.assertRaises( - exception.PolicyNotAuthorized, - self.controller._associate_host, - self.req, fakes.FAKE_UUID, body={'associate_host': 'fake_host'}) - self.assertEqual( - "Policy doesn't allow %s to be performed." % rule_name, - exc.format_message()) - class NetworksDeprecationTest(test.NoDBTestCase): @@ -737,32 +253,5 @@ class NetworksDeprecationTest(test.NoDBTestCase): 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, {}) diff --git a/nova/tests/unit/fake_policy.py b/nova/tests/unit/fake_policy.py index 53a5336ce2c7..e7c00716c030 100644 --- a/nova/tests/unit/fake_policy.py +++ b/nova/tests/unit/fake_policy.py @@ -57,9 +57,7 @@ policy_data = """ "os_compute_api:os-migrate-server:migrate": "", "os_compute_api:os-migrate-server:migrate_live": "", "os_compute_api:os-multinic": "", - "os_compute_api:os-networks": "", "os_compute_api:os-networks:view": "", - "os_compute_api:os-networks-associate": "", "os_compute_api:os-tenant-networks": "", "os_compute_api:os-pause-server:pause": "", "os_compute_api:os-pause-server:unpause": "", diff --git a/nova/tests/unit/test_policy.py b/nova/tests/unit/test_policy.py index e261d59b0dbf..b19c4539f2b3 100644 --- a/nova/tests/unit/test_policy.py +++ b/nova/tests/unit/test_policy.py @@ -346,8 +346,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase): "os_compute_api:os-lock-server:unlock:unlock_override", "os_compute_api:os-migrate-server:migrate", "os_compute_api:os-migrate-server:migrate_live", -"os_compute_api:os-networks", -"os_compute_api:os-networks-associate", "os_compute_api:os-quota-sets:update", "os_compute_api:os-quota-sets:delete", "os_compute_api:os-server-diagnostics", diff --git a/releasenotes/notes/remove-nova-network-c02953ba72a1795d.yaml b/releasenotes/notes/remove-nova-network-c02953ba72a1795d.yaml index fa63e969ffe0..b618b2bb248f 100644 --- a/releasenotes/notes/remove-nova-network-c02953ba72a1795d.yaml +++ b/releasenotes/notes/remove-nova-network-c02953ba72a1795d.yaml @@ -10,7 +10,16 @@ upgrade: * ``POST /os-security-group-default-rules`` * ``GET /os-security-group-default-rules/{id}`` * ``DELETE /os-security-group-default-rules/{id}`` + * ``POST /os-networks`` + * ``DELETE /os-networks`` + * ``POST /os-networks/add`` + * ``POST /os-networks/{id} (associate_host)`` + * ``POST /os-networks/{id} (disassociate)`` + * ``POST /os-networks/{id} (disassociate_host)`` + * ``POST /os-networks/{id} (disassociate_project)`` The following policies have also been removed. * ``os_compute_api:os-security-group-default-rules`` + * ``os_compute_api:os-networks`` + * ``os_compute_api:os-networks-associate``