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 <sfinucan@redhat.com>
This commit is contained in:
parent
3776e97f12
commit
1b71252a5f
@ -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
|
||||
<https://docs.openstack.org/api-ref/network/v2/#networks>`__.
|
||||
.. 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
|
||||
-------
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
----
|
||||
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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(),
|
||||
|
@ -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,
|
||||
|
@ -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
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"associate_host": "%(host)s"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"disassociate_host": null
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"disassociate_project": null
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"disassociate": null
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"id": "1"
|
||||
}
|
@ -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"
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -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])
|
||||
|
@ -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])
|
||||
|
@ -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, {})
|
||||
|
@ -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": "",
|
||||
|
@ -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",
|
||||
|
@ -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``
|
||||
|
Loading…
Reference in New Issue
Block a user