Merge "Remove (most) '/os-networks' REST APIs"
This commit is contained in:
commit
991d675675
@ -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…
x
Reference in New Issue
Block a user