Skip to content

Commit

Permalink
Remove '/os-tenant-networks' REST API
Browse files Browse the repository at this point in the history
Like '/os-networks', we can't remove this in its entirety due to the
fact that some of these are proxy URLs that also work with neutron.
These are retained but everything else is nuked.

Note that this highlights a bug in the API, whereby a missing
'objects.Network.cidr' value results in a value of 'None' being output
over the API. Clearly this is incorrect, but it's probably not worth
fixing for this deprecated API.

Change-Id: I31cb0891144bdd7945479bb6692b0a533de4c5d0
Signed-off-by: Stephen Finucane <[email protected]>
  • Loading branch information
stephenfin committed Nov 22, 2019
1 parent 991d675 commit e5e477c
Show file tree
Hide file tree
Showing 13 changed files with 30 additions and 453 deletions.
12 changes: 6 additions & 6 deletions api-ref/source/os-tenant-network.inc
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
.. -*- rst -*-
.. NOTE(gmann): These APIs are deprecated so do not update this
file even body, example or parameters are not complete.
===================================================
====================================================
Project networks (os-tenant-networks) (DEPRECATED)
===================================================
====================================================

.. warning::

Expand Down Expand Up @@ -57,7 +55,8 @@ through the ``policy.json`` file.

Normal response codes: 200

Error response codes: badRequest(400), unauthorized(401), forbidden(403), conflict(409), serviceUnavailable(503)
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
conflict(409), gone(410), serviceUnavailable(503)

**Example Create Project Network: JSON request**

Expand Down Expand Up @@ -121,7 +120,8 @@ can change 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
-------
Expand Down
11 changes: 3 additions & 8 deletions doc/api_samples/os-tenant-networks/networks-list-res.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
{
"networks": [
{
"cidr": "10.0.0.0/29",
"id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
"label": "test_0"
},
{
"cidr": "10.0.0.8/29",
"id": "616fb98f-46ca-475e-917e-2563e5a8cd20",
"label": "test_1"
"cidr": "None",
"id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
"label": "private"
}
]
}
6 changes: 6 additions & 0 deletions nova/api/openstack/compute/rest_api_version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,12 @@ API endpoints as below::
release. On deployments newer than this, some endpoints of the API will
return HTTP 410 (Gone) regadless of the requested microversion.

.. versionchanged:: 21.0.0

The ``os-tenant-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
----

Expand Down
44 changes: 0 additions & 44 deletions nova/api/openstack/compute/schemas/tenant_networks.py

This file was deleted.

88 changes: 4 additions & 84 deletions nova/api/openstack/compute/tenant_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,17 @@
# License for the specific language governing permissions and limitations
# under the License.


import netaddr
import netaddr.core as netexc
from oslo_log import log as logging
import six
from webob import exc

from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.compute.schemas import tenant_networks as schema
from nova.api.openstack import wsgi
from nova.api import validation
import nova.conf
from nova import context as nova_context
from nova import exception
from nova.i18n import _
import nova.network
from nova import objects
from nova.policies import tenant_networks as tn_policies
from nova import quota

Expand Down Expand Up @@ -97,86 +90,13 @@ def show(self, req, id):
raise exc.HTTPNotFound(explanation=msg)
return {'network': network_dict(network)}

@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((403, 404, 409))
@wsgi.response(202)
@wsgi.expected_errors(410)
def delete(self, req, id):
context = req.environ['nova.context']
context.can(tn_policies.BASE_POLICY_NAME)
raise exc.HTTPGone()

try:
self.network_api.disassociate(context, id)
self.network_api.delete(context, id)
except exception.PolicyNotAuthorized as e:
raise exc.HTTPForbidden(explanation=six.text_type(e))
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, 403, 409, 503))
@validation.schema(schema.create)
@wsgi.expected_errors(410)
def create(self, req, body):
context = req.environ["nova.context"]
context.can(tn_policies.BASE_POLICY_NAME)

network = body["network"]
keys = ["cidr", "cidr_v6", "ipam", "vlan_start", "network_size",
"num_networks"]
kwargs = {k: network.get(k) for k in keys}

label = network["label"]

if kwargs["cidr"]:
try:
net = netaddr.IPNetwork(kwargs["cidr"])
if net.size < 4:
msg = _("Requested network does not contain "
"enough (2+) usable hosts")
raise exc.HTTPBadRequest(explanation=msg)
except netexc.AddrConversionError:
msg = _("Address could not be converted.")
raise exc.HTTPBadRequest(explanation=msg)

try:
if CONF.enable_network_quota:
objects.Quotas.check_deltas(context, {'networks': 1},
context.project_id)
except exception.OverQuota:
msg = _("Quota exceeded, too many networks.")
raise exc.HTTPForbidden(explanation=msg)

kwargs['project_id'] = context.project_id

try:
networks = self.network_api.create(context,
label=label, **kwargs)
except exception.PolicyNotAuthorized as e:
raise exc.HTTPForbidden(explanation=six.text_type(e))
except exception.CidrConflict as e:
raise exc.HTTPConflict(explanation=e.format_message())
except Exception:
msg = _("Create networks failed")
LOG.exception(msg, extra=network)
raise exc.HTTPServiceUnavailable(explanation=msg)

# NOTE(melwitt): We recheck the quota after creating the object to
# prevent users from allocating more resources than their allowed quota
# in the event of a race. This is configurable because it can be
# expensive if strict quota limits are not required in a deployment.
if CONF.quota.recheck_quota and CONF.enable_network_quota:
try:
objects.Quotas.check_deltas(context, {'networks': 0},
context.project_id)
except exception.OverQuota:
self.network_api.delete(context,
network_dict(networks[0])['id'])
msg = _("Quota exceeded, too many networks.")
raise exc.HTTPForbidden(explanation=msg)

return {"network": network_dict(networks[0])}
raise exc.HTTPGone()


def _network_count(context, project_id):
Expand Down
7 changes: 0 additions & 7 deletions nova/api/validation/parameter_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,6 @@ def valid_char(char):
'pattern': '^[0-9]*$', 'minimum': 0, 'minLength': 1
}

# This only be used by nova-network specific APIs. It will be removed when
# those API removed.
positive_integer_with_empty_str = {
'type': ['integer', 'string'],
'pattern': '^[0-9]*$', 'minimum': 1,
}

hostname = {
'type': 'string', 'minLength': 1, 'maxLength': 255,
# NOTE: 'host' is defined in "services" table, and that
Expand Down
12 changes: 0 additions & 12 deletions nova/policies/tenant_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,10 @@
'method': 'GET',
'path': '/os-tenant-networks'
},

{
'method': 'POST',
'path': '/os-tenant-networks'
},

{
'method': 'GET',
'path': '/os-tenant-networks/{network_id}'
},

{
'method': 'DELETE',
'path': '/os-tenant-networks/{network_id}'
}

]),
]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
{
"networks": [
{
"cidr": "10.0.0.0/29",
"id": "%(id)s",
"label": "test_0"
},
{
"cidr": "10.0.0.8/29",
"id": "%(id)s",
"label": "test_1"
"cidr": "None",
"id": "%(uuid)s",
"label": "private"
}
]
}

This file was deleted.

This file was deleted.

36 changes: 4 additions & 32 deletions nova/tests/functional/api_sample_tests/test_tenant_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.


from oslo_serialization import jsonutils

import nova.conf
from nova.tests import fixtures as nova_fixtures
from nova.tests.functional.api_sample_tests import api_sample_base

CONF = nova.conf.CONF


# TODO(stephenfin): Remove the parts of this test that are nova-network only
class TenantNetworksJsonTests(api_sample_base.ApiSampleTestBaseV21):
USE_NEUTRON = False # partially nova-net only
ADMIN_API = True
sample_dir = "os-tenant-networks"

def setUp(self):
super(TenantNetworksJsonTests, self).setUp()
CONF.set_override("enable_network_quota", True)
self.useFixture(nova_fixtures.RegisterNetworkQuota())

def fake(*args, **kwargs):
pass

self.stub_out("nova.quota.QUOTAS.reserve", fake)
self.stub_out("nova.quota.QUOTAS.commit", fake)
self.stub_out("nova.quota.QUOTAS.rollback", fake)
self.stub_out("nova.quota.QuotaEngine.reserve", fake)
self.stub_out("nova.quota.QuotaEngine.commit", fake)
self.stub_out("nova.quota.QuotaEngine.rollback", fake)

# TODO(stephenfin): Rework this to work with neutron
def test_list_networks(self):
response = self._do_get('os-tenant-networks')
self._verify_response('networks-list-res', {}, response, 200)

# TODO(stephenfin): Remove this API since it's nova-network only
def test_create_network(self):
response = self._do_post('os-tenant-networks', "networks-post-req", {})
self._verify_response('networks-post-res', {}, response, 200)
self.api.api_post('os-tenant-networks', {},
check_response_status=[410])

# TODO(stephenfin): Remove this API since it's nova-network only
def test_delete_network(self):
response = self._do_post('os-tenant-networks', "networks-post-req", {})
net = jsonutils.loads(response.content)
response = self._do_delete('os-tenant-networks/%s' %
net["network"]["id"])
self.assertEqual(202, response.status_code)
self.assertEqual("", response.text)
self.api.api_delete('os-tenant-networks/1',
check_response_status=[410])
Loading

0 comments on commit e5e477c

Please sign in to comment.