Remove support for /os-virtual-interfaces REST API

This drops support for the os-virtual-interfaces compute REST API
which has been deprecated since Newton:

  I1a8a44530be29292561e90d6f7bd7ed512a88ee3

Now it returns 410 response.

Unit tests are removed and the functional API sample test is just
asserting the 410 response now. 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 os-virtual-interfaces was
removed.

Depends-On: https://review.openstack.org/571556/

Part of blueprint remove-nova-network

Change-Id: Id7f94a643e5d7b8a842c0f4a5c9f796d6566b365
This commit is contained in:
jichen 2018-05-16 11:15:03 +08:00 committed by Matt Riedemann
parent d5202b5561
commit 4c93003ede
13 changed files with 22 additions and 325 deletions

View File

@ -69,7 +69,6 @@ the `API guide <http://developer.openstack.org/api-guide/compute/index.html>`_.
.. include:: os-security-group-default-rules.inc .. include:: os-security-group-default-rules.inc
.. include:: os-security-group-rules.inc .. include:: os-security-group-rules.inc
.. include:: os-hosts.inc .. include:: os-hosts.inc
.. include:: os-virtual-interfaces.inc
============= =============
Obsolete APIs Obsolete APIs
@ -81,3 +80,4 @@ Compute API in the past, but no longer exist.
.. include:: os-certificates.inc .. include:: os-certificates.inc
.. include:: os-cloudpipe.inc .. include:: os-cloudpipe.inc
.. include:: os-fping.inc .. include:: os-fping.inc
.. include:: os-virtual-interfaces.inc

View File

@ -8,8 +8,10 @@ Lists virtual interfaces for a server.
.. warning:: Since this API is only implemented for the nova-network, the API .. warning:: Since this API is only implemented for the nova-network, the API
is deprecated from the Microversion 2.44. This API will fail with is deprecated from the Microversion 2.44. This API will fail with
a 404 starting from microversion 2.44. To query the server attached a 404 starting from microversion 2.44. It was removed in the
neutron interface, please use the API 18.0.0 Rocky release.
To query the server attached neutron interface, please use the API
``GET /servers/{server_uuid}/os-interface``. ``GET /servers/{server_uuid}/os-interface``.
.. note:: .. note::
@ -32,7 +34,8 @@ the server to perform this operation. Change these permissions through the
Normal response codes: 200 Normal response codes: 200
Error response codes: badRequest(400), unauthorized(401), forbidden(403), itemNotFound(404) Error response codes: badRequest(400), unauthorized(401), forbidden(403),
itemNotFound(404), gone(410)
Request Request
------- -------

View File

@ -15,61 +15,13 @@
"""The virtual interfaces extension.""" """The virtual interfaces extension."""
import webob from webob import exc
from nova.api.openstack import api_version_request
from nova.api.openstack import common
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova import compute
from nova.i18n import _
from nova import network
from nova.policies import virtual_interfaces as vif_policies
def _translate_vif_summary_view(req, vif):
"""Maps keys for VIF summary view."""
d = {}
d['id'] = vif.uuid
d['mac_address'] = vif.address
if api_version_request.is_supported(req, min_version='2.12'):
d['net_id'] = vif.net_uuid
# NOTE(gmann): This is for v2.1 compatible mode where response should be
# same as v2 one.
if req.is_legacy_v2():
d['OS-EXT-VIF-NET:net_id'] = vif.net_uuid
return d
class ServerVirtualInterfaceController(wsgi.Controller): class ServerVirtualInterfaceController(wsgi.Controller):
"""The instance VIF API controller for the OpenStack API.
This API is deprecated from the Microversion '2.44'. @wsgi.expected_errors((410))
"""
def __init__(self):
self.compute_api = compute.API()
self.network_api = network.API()
super(ServerVirtualInterfaceController, self).__init__()
def _items(self, req, server_id, entity_maker):
"""Returns a list of VIFs, transformed through entity_maker."""
context = req.environ['nova.context']
context.can(vif_policies.BASE_POLICY_NAME)
instance = common.get_instance(self.compute_api, context, server_id)
try:
vifs = self.network_api.get_vifs_by_instance(context, instance)
except NotImplementedError:
msg = _('Listing virtual interfaces is not supported by this '
'cloud.')
raise webob.exc.HTTPBadRequest(explanation=msg)
limited_list = common.limited(vifs, req)
res = [entity_maker(req, vif) for vif in limited_list]
return {'virtual_interfaces': res}
@wsgi.Controller.api_version("2.1", "2.43")
@wsgi.expected_errors((400, 404))
def index(self, req, server_id): def index(self, req, server_id):
"""Returns the list of VIFs for a given instance.""" raise exc.HTTPGone()
return self._items(req, server_id,
entity_maker=_translate_vif_summary_view)

View File

@ -83,7 +83,6 @@ from nova.policies import simple_tenant_usage
from nova.policies import suspend_server from nova.policies import suspend_server
from nova.policies import tenant_networks from nova.policies import tenant_networks
from nova.policies import used_limits from nova.policies import used_limits
from nova.policies import virtual_interfaces
from nova.policies import volumes from nova.policies import volumes
from nova.policies import volumes_attachments from nova.policies import volumes_attachments
@ -160,7 +159,6 @@ def list_rules():
suspend_server.list_rules(), suspend_server.list_rules(),
tenant_networks.list_rules(), tenant_networks.list_rules(),
used_limits.list_rules(), used_limits.list_rules(),
virtual_interfaces.list_rules(),
volumes.list_rules(), volumes.list_rules(),
volumes_attachments.list_rules() volumes_attachments.list_rules()
) )

View File

@ -1,41 +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-virtual-interfaces'
virtual_interfaces_policies = [
policy.DocumentedRuleDefault(
BASE_POLICY_NAME,
base.RULE_ADMIN_OR_OWNER,
"""List virtual interfaces.
This works only with the nova-network service, which is now deprecated""",
[
{
'method': 'GET',
'path': '/servers/{server_id}/os-virtual-interfaces'
}
]),
]
def list_rules():
return virtual_interfaces_policies

View File

@ -1,9 +0,0 @@
{
"virtual_interfaces": [
{
"id": "%(id)s",
"mac_address": "%(mac_addr)s",
"net_id": "%(id)s"
}
]
}

View File

@ -1,9 +0,0 @@
{
"virtual_interfaces": [
{
"id": "%(id)s",
"mac_address": "%(mac_addr)s",
"OS-EXT-VIF-NET:net_id": "%(id)s"
}
]
}

View File

@ -1,8 +0,0 @@
{
"virtual_interfaces": [
{
"id": "%(id)s",
"mac_address": "%(mac_addr)s"
}
]
}

View File

@ -13,30 +13,19 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from nova.tests.functional.api_sample_tests import test_servers
from nova.tests.functional.api import client as api_client
from nova.tests.functional import api_samples_test_base
from nova.tests import uuidsentinel as uuids
class VirtualInterfacesJsonTest(test_servers.ServersSampleBase): class VirtualInterfacesJsonTest(api_samples_test_base.ApiSampleTestBase):
sample_dir = "os-virtual-interfaces" api_major_version = 'v2'
def setUp(self):
super(VirtualInterfacesJsonTest, self).setUp()
self.template = 'vifs-list-resp'
if self.api_major_version == 'v2':
self.template = 'vifs-list-resp-v2'
def test_vifs_list(self): def test_vifs_list(self):
uuid = self._post_server() uuid = uuids.instance_1
response = self._do_get('servers/%s/os-virtual-interfaces' % uuid) ex = self.assertRaises(api_client.OpenStackApiException,
self.api.api_get,
subs = {'mac_addr': '(?:[a-f0-9]{2}:){5}[a-f0-9]{2}'} '/servers/%s/os-virtual-interfaces' % uuid)
self._verify_response(self.template, subs, response, 200) self.assertEqual(410, ex.response.status_code)
class VirtualInterfacesJsonV212Test(VirtualInterfacesJsonTest):
microversion = '2.12'
# NOTE(gmann): microversion tests do not need to run for v2 API
# so defining scenarios only for v2.12 which will run the original tests
# by appending '(v2_12)' in test_id.
scenarios = [('v2_12', {'api_major_version': 'v2.1'})]

View File

@ -1,177 +0,0 @@
# Copyright (C) 2011 Midokura KK
# 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.
import mock
import webob
from nova.api.openstack import api_version_request
from nova.api.openstack.compute import virtual_interfaces as vi21
from nova import compute
from nova.compute import api as compute_api
from nova import context
from nova import exception
from nova import network
from nova.objects import virtual_interface as vif_obj
from nova import test
from nova.tests.unit.api.openstack import fakes
from nova.tests import uuidsentinel as uuids
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
def compute_api_get(context, instance_id, expected_attrs=None):
return dict(uuid=FAKE_UUID, id=instance_id, instance_type_id=1, host='bob')
def _generate_fake_vifs(context):
vif = vif_obj.VirtualInterface(context=context)
vif.address = '00-00-00-00-00-00'
vif.network_id = 123
vif.net_uuid = '22222222-2222-2222-2222-22222222222222222'
vif.uuid = uuids.vif1_uuid
fake_vifs = [vif]
vif = vif_obj.VirtualInterface(context=context)
vif.address = '11-11-11-11-11-11'
vif.network_id = 456
vif.net_uuid = '33333333-3333-3333-3333-33333333333333333'
vif.uuid = uuids.vif2_uuid
fake_vifs.append(vif)
return fake_vifs
def get_vifs_by_instance(context, instance_id):
return _generate_fake_vifs(context)
class FakeRequest(object):
def __init__(self, context):
self.environ = {'nova.context': context}
class ServerVirtualInterfaceTestV21(test.NoDBTestCase):
wsgi_api_version = '2.1'
expected_response = {
'virtual_interfaces': [
{'id': uuids.vif1_uuid,
'mac_address': '00-00-00-00-00-00'},
{'id': uuids.vif2_uuid,
'mac_address': '11-11-11-11-11-11'}]}
def setUp(self):
super(ServerVirtualInterfaceTestV21, self).setUp()
# These APIs aren't implemented by the neutronv2 API code in Nova so
# the tests need to specifically run against nova-network unless
# otherwise setup to run with Neutron and expect failure.
self.flags(use_neutron=False)
self.compute_api_get_patcher = mock.patch.object(
compute.api.API, "get",
side_effect=compute_api_get)
self.get_vifs_by_instance_patcher = mock.patch.object(
network.api.API, "get_vifs_by_instance",
side_effect=get_vifs_by_instance)
self.compute_api_get_patcher.start()
self.get_vifs_by_instance_patcher.start()
self.addCleanup(self.compute_api_get_patcher.stop)
self.addCleanup(self.get_vifs_by_instance_patcher.stop)
self._set_controller()
def _set_controller(self):
self.controller = vi21.ServerVirtualInterfaceController()
def test_get_virtual_interfaces_list(self):
req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
res_dict = self.controller.index(req, 'fake_uuid')
self.assertEqual(self.expected_response, res_dict)
def test_get_virtual_interfaces_list_offset_and_limit(self):
path = '/v2/fake/os-virtual-interfaces?offset=1&limit=1'
req = fakes.HTTPRequest.blank(path, version=self.wsgi_api_version)
res_dict = self.controller.index(req, 'fake_uuid')
name = 'virtual_interfaces'
limited_response = {name: [self.expected_response[name][1]]}
self.assertEqual(limited_response, res_dict)
@mock.patch.object(compute_api.API, 'get',
side_effect=exception.InstanceNotFound(
instance_id='instance-0000'))
def test_vif_instance_not_found(self, mock_get):
fake_context = context.RequestContext('fake', 'fake')
fake_req = FakeRequest(fake_context)
fake_req.api_version_request = api_version_request.APIVersionRequest(
self.wsgi_api_version)
self.assertRaises(
webob.exc.HTTPNotFound,
self.controller.index,
fake_req, 'fake_uuid')
mock_get.assert_called_once_with(fake_context,
'fake_uuid',
expected_attrs=None)
def test_list_vifs_neutron_notimplemented(self):
"""Tests that a 400 is returned when using neutron as the backend"""
# unset the get_vifs_by_instance stub from setUp
self.get_vifs_by_instance_patcher.stop()
self.flags(use_neutron=True)
# reset the controller to use the neutron network API
self._set_controller()
req = fakes.HTTPRequest.blank('', version=self.wsgi_api_version)
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req, FAKE_UUID)
self.get_vifs_by_instance_patcher.start()
class ServerVirtualInterfaceTestV212(ServerVirtualInterfaceTestV21):
wsgi_api_version = '2.12'
expected_response = {
'virtual_interfaces': [
{'id': uuids.vif1_uuid,
'mac_address': '00-00-00-00-00-00',
'net_id': '22222222-2222-2222-2222-22222222222222222'},
{'id': uuids.vif2_uuid,
'mac_address': '11-11-11-11-11-11',
'net_id': '33333333-3333-3333-3333-33333333333333333'}]}
class ServerVirtualInterfaceEnforcementV21(test.NoDBTestCase):
def setUp(self):
super(ServerVirtualInterfaceEnforcementV21, self).setUp()
self.controller = vi21.ServerVirtualInterfaceController()
self.req = fakes.HTTPRequest.blank('')
def test_index_virtual_interfaces_policy_failed(self):
rule_name = "os_compute_api:os-virtual-interfaces"
self.policy.set_rules({rule_name: "project:non_fake"})
exc = self.assertRaises(
exception.PolicyNotAuthorized,
self.controller.index, self.req, fakes.FAKE_UUID)
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
class ServerVirtualInterfaceDeprecationTest(test.NoDBTestCase):
def setUp(self):
super(ServerVirtualInterfaceDeprecationTest, self).setUp()
self.controller = vi21.ServerVirtualInterfaceController()
self.req = fakes.HTTPRequest.blank('', version='2.44')
def test_index_not_found(self):
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.index, self.req, FAKE_UUID)

View File

@ -97,7 +97,6 @@ policy_data = """
"os_compute_api:os-shelve:unshelve": "", "os_compute_api:os-shelve:unshelve": "",
"os_compute_api:os-suspend-server:suspend": "", "os_compute_api:os-suspend-server:suspend": "",
"os_compute_api:os-suspend-server:resume": "", "os_compute_api:os-suspend-server:resume": "",
"os_compute_api:os-virtual-interfaces": "",
"os_compute_api:os-volumes": "", "os_compute_api:os-volumes": "",
"os_compute_api:os-volumes-attachments:index": "", "os_compute_api:os-volumes-attachments:index": "",
"os_compute_api:os-volumes-attachments:show": "", "os_compute_api:os-volumes-attachments:show": "",

View File

@ -433,7 +433,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-server-groups:delete", "os_compute_api:os-server-groups:delete",
"os_compute_api:os-shelve:shelve", "os_compute_api:os-shelve:shelve",
"os_compute_api:os-shelve:unshelve", "os_compute_api:os-shelve:unshelve",
"os_compute_api:os-virtual-interfaces",
"os_compute_api:os-volumes", "os_compute_api:os-volumes",
"os_compute_api:os-volumes-attachments:index", "os_compute_api:os-volumes-attachments:index",
"os_compute_api:os-volumes-attachments:show", "os_compute_api:os-volumes-attachments:show",

View File

@ -8,6 +8,7 @@ upgrade:
* ``GET /os-fping`` * ``GET /os-fping``
* ``GET /os-fping/{server_id}`` * ``GET /os-fping/{server_id}``
* ``GET /servers/{server_id}/os-virtual-interfaces``
In addition, the following configuration options have been removed. In addition, the following configuration options have been removed.