Drop OPENSTACK_NOVA_EXTENSIONS_BLACKLIST finally

Part of the removal of OPENSTACK_NOVA_EXTENSIONS_BLACKLIST (3/3)

Clean up nova extensions related code in the API layer.

Change-Id: I9730095365342cac1023f4112bae4b3a28cdeaf7
This commit is contained in:
Akihiro Motoki 2020-09-12 09:16:13 +09:00
parent 3c6286a9e9
commit 672c43c43e
7 changed files with 13 additions and 218 deletions

View File

@ -2312,41 +2312,6 @@ Note that when disabling the query to neutron it takes some time until
associated floating IPs are visible in the project instance table and associated floating IPs are visible in the project instance table and
users may reload the table to check them. users may reload the table to check them.
OPENSTACK_NOVA_EXTENSIONS_BLACKLIST
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 8.0.0(Liberty)
.. deprecated:: 17.2.0(Ussuri)
Default: ``[]``
Ignore all listed Nova extensions, and behave as if they were unsupported.
Can be used to selectively disable certain costly extensions for performance
reasons.
Along with the deprecation, the current plan on individual effective values
in this setting is as follows.
The support of ``SimpleTenantUsage`` will be replaced by a new setting which
controls whether ``SimpleTenantUsage`` nova API feature is used or not
(not implemented yet as of Victoria; planned in Wallaby release).
This setting will not be droped until the new setting is implemented.
The support of the following values will be simply dropped
as nova provides all features in the recent API versions.
* ``AdminActions``
* ``Aggregates``
* ``BlockDeviceMappingV2Boot``
* ``ConfigDrive``
* ``DiskConfig``
* ``Keypairs``
* ``SchedulerHints``
* ``ServerGroups``
* ``Services``
* ``Shelve``
OPENSTACK_USE_SIMPLE_TENANT_USAGE OPENSTACK_USE_SIMPLE_TENANT_USAGE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -22,7 +22,6 @@ import collections
import logging import logging
from operator import attrgetter from operator import attrgetter
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from novaclient import api_versions from novaclient import api_versions
@ -46,114 +45,6 @@ INSTANCE_ACTIVE_STATE = 'ACTIVE'
VOLUME_STATE_AVAILABLE = "available" VOLUME_STATE_AVAILABLE = "available"
DEFAULT_QUOTA_NAME = 'default' DEFAULT_QUOTA_NAME = 'default'
# python-novaclient 16.0.0 removed the list_extensions module and the
# GET /extensions API is deprecated since Newton. Furthermore, the ability
# to enable/disable compute API extensions was also removed in Newton.
# Therefore we hard-code the list of extensions here until the
# OPENSTACK_NOVA_EXTENSIONS_BLACKLIST setting is no longer used.
EXTENSIONS = (
'AccessIPs',
'AdminActions',
'AdminPassword',
'Agents',
'Aggregates',
'AssistedVolumeSnapshots',
'AttachInterfaces',
'AvailabilityZone',
'BareMetalExtStatus',
'BareMetalNodes',
'BlockDeviceMapping',
'BlockDeviceMappingV2Boot',
'CellCapacities',
'Cells',
'Certificates',
'Cloudpipe',
'CloudpipeUpdate',
'ConfigDrive',
'ConsoleAuthTokens',
'ConsoleOutput',
'Consoles',
'CreateBackup',
'Createserverext',
'DeferredDelete',
'DiskConfig',
'Evacuate',
'ExtendedAvailabilityZone',
'ExtendedEvacuateFindHost',
'ExtendedFloatingIps',
'ExtendedHypervisors',
'ExtendedIps',
'ExtendedIpsMac',
'ExtendedNetworks',
'ExtendedQuotas',
'ExtendedRescueWithImage',
'ExtendedServerAttributes',
'ExtendedServices',
'ExtendedServicesDelete',
'ExtendedStatus',
'ExtendedStatus',
'ExtendedVolumes',
'FixedIPs',
'FlavorAccess',
'FlavorDisabled',
'FlavorExtraData',
'FlavorExtraSpecs',
'FlavorManage',
'FlavorRxtx',
'FlavorSwap',
'FloatingIpDns',
'FloatingIpPools',
'FloatingIps',
'FloatingIpsBulk',
'Fping',
'HideServerAddresses',
'Hosts',
'HypervisorStatus',
'Hypervisors',
'ImageSize',
'InstanceActions',
'Keypairs',
'LockServer',
'MigrateServer',
'Migrations',
'Multinic',
'MultipleCreate',
'NetworkAssociationSupport',
'Networks',
'OSInstanceUsageAuditLog',
'OSTenantNetworks',
'PauseServer',
'Personality',
'PreserveEphemeralOnRebuild',
'QuotaClasses',
'Quotas',
'Rescue',
'SchedulerHints',
'SecurityGroupDefaultRules',
'SecurityGroups',
'ServerDiagnostics',
'ServerExternalEvents',
'ServerGroupQuotas',
'ServerGroups',
'ServerListMultiStatus',
'ServerPassword',
'ServerSortKeys',
'ServerStartStop',
'ServerUsage',
'Services',
'Shelve',
'SimpleTenantUsage',
'SuspendServer',
'UsedLimits',
'UsedLimitsForAdmin',
'UserData',
'UserQuotas',
'VirtualInterfaces',
'VolumeAttachmentUpdate',
'Volumes'
)
get_microversion = _nova.get_microversion get_microversion = _nova.get_microversion
server_get = _nova.server_get server_get = _nova.server_get
Server = _nova.Server Server = _nova.Server
@ -1124,27 +1015,6 @@ def interface_detach(request, server, port_id):
return _nova.novaclient(request).servers.interface_detach(server, port_id) return _nova.novaclient(request).servers.interface_detach(server, port_id)
@profiler.trace
@memoized.memoized
def list_extensions(request):
"""List all nova extension names, except the ones in the blacklist."""
blacklist = set(settings.OPENSTACK_NOVA_EXTENSIONS_BLACKLIST)
return tuple(
extension for extension in EXTENSIONS if extension not in blacklist
)
@profiler.trace
@memoized.memoized
def extension_supported(extension_name, request):
"""Determine if nova supports a given extension name.
Example values for the extension_name include AdminActions, ConsoleOutput,
etc.
"""
return extension_name in list_extensions(request)
@profiler.trace @profiler.trace
def can_set_server_password(): def can_set_server_password():
return utils.get_dict_config('OPENSTACK_HYPERVISOR_FEATURES', return utils.get_dict_config('OPENSTACK_HYPERVISOR_FEATURES',

View File

@ -120,11 +120,9 @@ class Services(generic.View):
def get(self, request): def get(self, request):
"""Get a list of nova services. """Get a list of nova services.
Will return HTTP 501 status code if the service_list extension is Will return HTTP 501 status code if the compute service is enabled.
not supported.
""" """
if (api.base.is_service_enabled(request, 'compute') and if api.base.is_service_enabled(request, 'compute'):
api.nova.extension_supported('Services', request)):
result = api.nova.service_list(request) result = api.nova.service_list(request)
return {'items': [u.to_dict() for u in result]} return {'items': [u.to_dict() for u in result]}
raise rest_utils.AjaxError(501, '') raise rest_utils.AjaxError(501, '')
@ -347,7 +345,7 @@ class Servers(generic.View):
:param name: The new server name. :param name: The new server name.
:param source_id: The ID of the image to use. :param source_id: The ID of the image to use.
:param flavor_id: The ID of the flavor to use. :param flavor_id: The ID of the flavor to use.
:param key_name: (optional extension) name of previously created :param key_name: (optional) name of previously created
keypair to inject into the instance. keypair to inject into the instance.
:param user_data: user data to pass to be exposed by the metadata :param user_data: user data to pass to be exposed by the metadata
server this can be a file type object as well or a server this can be a file type object as well or a
@ -501,25 +499,6 @@ class ServerMetadata(generic.View):
api.nova.server_metadata_delete(request, server_id, removed) api.nova.server_metadata_delete(request, server_id, removed)
@urls.register
class Extensions(generic.View):
"""API for nova extensions."""
url_regex = r'nova/extensions/$'
@rest_utils.ajax()
def get(self, request):
"""Get a list of extensions.
The listing result is an object with property "items". Each item is
an object with property "name".
Example GET:
http://localhost/api/nova/extensions
"""
result = api.nova.list_extensions(request)
return {'items': [{'name': e} for e in result]}
@urls.register @urls.register
class Flavors(generic.View): class Flavors(generic.View):
"""API for nova flavors.""" """API for nova flavors."""

View File

@ -461,8 +461,6 @@ OPENSTACK_NEUTRON_NETWORK = {
# a performance issue in the project instance table in large deployments. # a performance issue in the project instance table in large deployments.
OPENSTACK_INSTANCE_RETRIEVE_IP_ADDRESSES = True OPENSTACK_INSTANCE_RETRIEVE_IP_ADDRESSES = True
OPENSTACK_NOVA_EXTENSIONS_BLACKLIST = []
# This setting controls whether SimpleTenantUsage nova API is used in the usage # This setting controls whether SimpleTenantUsage nova API is used in the usage
# overview. According to feedbacks to the horizon team, the usage of # overview. According to feedbacks to the horizon team, the usage of
# SimpleTenantUsage can cause performance issues in the nova API in larger # SimpleTenantUsage can cause performance issues in the nova API in larger

View File

@ -483,19 +483,6 @@ class NovaRestTestCase(test.TestCase):
request, '1', ['c', 'd'] request, '1', ['c', 'd']
) )
#
# Extensions
#
@test.create_mocks({api.nova: ['list_extensions']})
def test_extension_list(self):
request = self.mock_rest_request()
self.mock_list_extensions.return_value = ['foo', 'bar']
response = nova.Extensions().get(request)
self.assertStatusCode(response, 200)
self.assertEqual({"items": [{"name": "foo"}, {"name": "bar"}]},
response.json)
self.mock_list_extensions.assert_called_once_with(request)
# #
# Flavors # Flavors
# #
@ -892,8 +879,7 @@ class NovaRestTestCase(test.TestCase):
# #
@test.create_mocks({api.base: ['is_service_enabled'], @test.create_mocks({api.base: ['is_service_enabled'],
api.nova: ['service_list', api.nova: ['service_list']})
'extension_supported']})
def test_services_get(self): def test_services_get(self):
request = self.mock_rest_request(GET={}) request = self.mock_rest_request(GET={})
self.mock_service_list.return_value = [ self.mock_service_list.return_value = [
@ -901,7 +887,6 @@ class NovaRestTestCase(test.TestCase):
mock.Mock(**{'to_dict.return_value': {'id': '2'}}) mock.Mock(**{'to_dict.return_value': {'id': '2'}})
] ]
self.mock_is_service_enabled.return_value = True self.mock_is_service_enabled.return_value = True
self.mock_extension_supported.return_value = True
response = nova.Services().get(request) response = nova.Services().get(request)
@ -911,8 +896,6 @@ class NovaRestTestCase(test.TestCase):
self.mock_service_list.assert_called_once_with(request) self.mock_service_list.assert_called_once_with(request)
self.mock_is_service_enabled.assert_called_once_with(request, self.mock_is_service_enabled.assert_called_once_with(request,
'compute') 'compute')
self.mock_extension_supported.assert_called_once_with(
'Services', request)
@mock.patch.object(api.base, 'is_service_enabled') @mock.patch.object(api.base, 'is_service_enabled')
def test_services_get_disabled(self, mock_is_service_enabled): def test_services_get_disabled(self, mock_is_service_enabled):

View File

@ -70,15 +70,6 @@ class ComputeApiTests(test.APIMockTestCase):
# To handle upgrade_api # To handle upgrade_api
mock_novaclient.api_version = api_versions.APIVersion(version) mock_novaclient.api_version = api_versions.APIVersion(version)
@override_settings(OPENSTACK_NOVA_EXTENSIONS_BLACKLIST=['ConsoleOutput'])
def test_extension_supported(self):
self.assertTrue(api.nova.extension_supported(
'Evacuate', mock.sentinel.request))
self.assertFalse(api.nova.extension_supported(
'ConsoleOutput', mock.sentinel.request))
self.assertFalse(api.nova.extension_supported(
'DoesNotExist', mock.sentinel.request))
@mock.patch.object(api._nova, 'novaclient') @mock.patch.object(api._nova, 'novaclient')
def test_server_reboot(self, mock_novaclient): def test_server_reboot(self, mock_novaclient):
server = self.servers.first() server = self.servers.first()

View File

@ -0,0 +1,9 @@
---
upgrade:
- |
``OPENSTACK_NOVA_EXTENSIONS_BLACKLIST`` setting is now dropped.
If you specify ``SimpleTenantUsage`` in this setting, consider setting
``OPENSTACK_USE_SIMPLE_TENANT_USAGE`` to ``False`` instead.
For other effective values in this setting, no replacement is
provided as nova provides all features in recent versions of nova API.
Note that you can enable/disable table actions via policy rules.