From a722640b2fea2beba9de4455ee27d38171d56fed Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 28 Jan 2025 17:51:32 +0000 Subject: [PATCH] api: Only check minimum API version As noted in [1], we were passing arguments to the 'is_supported' function inconsistently. Given we only have four easily converted users of the 'max_version' argument, we can simplify the calls by only passing a *minimum* API version and negating there where necessary. This is good enough for our use cases. [1] https://review.opendev.org/c/openstack/nova/+/936366/ Change-Id: I71a95b8b4b6b59485273f136f255811b6d57b657 Signed-off-by: Stephen Finucane --- nova/api/openstack/api_version_request.py | 14 ++-- nova/api/openstack/compute/aggregates.py | 2 +- nova/api/openstack/compute/create_backup.py | 4 +- nova/api/openstack/compute/evacuate.py | 21 +++--- nova/api/openstack/compute/flavor_access.py | 2 +- nova/api/openstack/compute/flavors.py | 22 +++---- .../openstack/compute/flavors_extraspecs.py | 4 +- nova/api/openstack/compute/hypervisors.py | 25 +++---- .../api/openstack/compute/instance_actions.py | 6 +- nova/api/openstack/compute/lock_server.py | 6 +- nova/api/openstack/compute/migrate_server.py | 12 ++-- .../openstack/compute/server_diagnostics.py | 2 +- nova/api/openstack/compute/server_groups.py | 4 +- nova/api/openstack/compute/server_shares.py | 2 +- nova/api/openstack/compute/servers.py | 65 ++++++++----------- nova/api/openstack/compute/services.py | 17 ++--- nova/api/openstack/compute/views/flavors.py | 9 +-- nova/api/openstack/compute/views/servers.py | 36 +++++----- nova/api/openstack/compute/volumes.py | 5 +- .../api/openstack/compute/test_servers.py | 7 +- .../api/openstack/test_api_version_request.py | 39 ++--------- 21 files changed, 121 insertions(+), 183 deletions(-) diff --git a/nova/api/openstack/api_version_request.py b/nova/api/openstack/api_version_request.py index 469aeb114ebc..676cc2ec0525 100644 --- a/nova/api/openstack/api_version_request.py +++ b/nova/api/openstack/api_version_request.py @@ -306,22 +306,18 @@ def max_api_version(): return APIVersionRequest(_MAX_API_VERSION) -def is_supported(req, min_version=_MIN_API_VERSION, - max_version=_MAX_API_VERSION): +def is_supported(req, version): """Check if API request version satisfies version restrictions. :param req: request object - :param min_version: minimal version of API needed for correct - request processing - :param max_version: maximum version of API needed for correct - request processing + :param version: minimal version of API needed for correct + request processing :returns: True if request satisfies minimal and maximum API version - requirements. False in other case. + requirements. False in other case. """ - return (APIVersionRequest(max_version) >= req.api_version_request >= - APIVersionRequest(min_version)) + return req.api_version_request >= APIVersionRequest(version) class APIVersionRequest(object): diff --git a/nova/api/openstack/compute/aggregates.py b/nova/api/openstack/compute/aggregates.py index a2fb9880d6d6..590c5c1da5cf 100644 --- a/nova/api/openstack/compute/aggregates.py +++ b/nova/api/openstack/compute/aggregates.py @@ -274,7 +274,7 @@ class AggregateController(wsgi.Controller): return {"aggregate": _aggregate} def _build_aggregate_items(self, req, aggregate): - show_uuid = api_version_request.is_supported(req, min_version="2.41") + show_uuid = api_version_request.is_supported(req, "2.41") keys = aggregate.obj_fields # NOTE(rlrossit): Within the compute API, metadata will always be # set on the aggregate object (at a minimum to {}). Because of this, diff --git a/nova/api/openstack/compute/create_backup.py b/nova/api/openstack/compute/create_backup.py index 45b876390766..4c2fc669bb3d 100644 --- a/nova/api/openstack/compute/create_backup.py +++ b/nova/api/openstack/compute/create_backup.py @@ -65,9 +65,7 @@ class CreateBackupController(wsgi.Controller): props = {} metadata = entity.get('metadata', {}) # Starting from microversion 2.39 we don't check quotas on createBackup - if api_version_request.is_supported( - req, max_version= - api_version_request.MAX_IMAGE_META_PROXY_API_VERSION): + if not api_version_request.is_supported(req, '2.39'): common.check_img_metadata_properties_quota(context, metadata) props.update(metadata) diff --git a/nova/api/openstack/compute/evacuate.py b/nova/api/openstack/compute/evacuate.py index cbf7cded6a77..d2d647c65cdc 100644 --- a/nova/api/openstack/compute/evacuate.py +++ b/nova/api/openstack/compute/evacuate.py @@ -45,7 +45,7 @@ class EvacuateController(wsgi.Controller): self.host_api = compute.HostAPI() def _get_on_shared_storage(self, req, evacuate_body): - if api_version_request.is_supported(req, min_version='2.14'): + if api_version_request.is_supported(req, '2.14'): return None else: return strutils.bool_from_string(evacuate_body["onSharedStorage"]) @@ -108,7 +108,7 @@ class EvacuateController(wsgi.Controller): force = None target_state = None - if api_version_request.is_supported(req, min_version='2.95'): + if api_version_request.is_supported(req, '2.95'): min_ver = objects.service.get_minimum_version_all_cells( context, ['nova-compute']) if min_ver < MIN_VER_NOVA_COMPUTE_EVACUATE_STOPPED: @@ -122,13 +122,13 @@ class EvacuateController(wsgi.Controller): on_shared_storage = self._get_on_shared_storage(req, evacuate_body) - if api_version_request.is_supported(req, min_version='2.29'): + if api_version_request.is_supported(req, '2.29'): force = body["evacuate"].get("force", False) force = strutils.bool_from_string(force, strict=True) if force is True and not host: message = _("Can't force to a non-provided destination") raise exc.HTTPBadRequest(explanation=message) - if api_version_request.is_supported(req, min_version='2.14'): + if api_version_request.is_supported(req, '2.14'): password = self._get_password_v214(req, evacuate_body) else: password = self._get_password(req, evacuate_body, @@ -151,8 +151,8 @@ class EvacuateController(wsgi.Controller): on_shared_storage, password, force, target_state) except exception.InstanceInvalidState as state_error: - common.raise_http_conflict_for_instance_invalid_state(state_error, - 'evacuate', id) + common.raise_http_conflict_for_instance_invalid_state( + state_error, 'evacuate', id) except ( exception.ComputeServiceInUse, exception.ForbiddenPortsWithAccelerator, @@ -163,11 +163,14 @@ class EvacuateController(wsgi.Controller): raise exc.HTTPConflict(explanation=e.format_message()) except ( exception.ForbiddenSharesNotSupported, - exception.ForbiddenWithShare) as e: + exception.ForbiddenWithShare, + ) as e: raise exc.HTTPConflict(explanation=e.format_message()) - if (not api_version_request.is_supported(req, min_version='2.14') and - CONF.api.enable_instance_password): + if ( + not api_version_request.is_supported(req, '2.14') and + CONF.api.enable_instance_password + ): return {'adminPass': password} else: return None diff --git a/nova/api/openstack/compute/flavor_access.py b/nova/api/openstack/compute/flavor_access.py index 92ae1e7fec09..4dec0d1a08d3 100644 --- a/nova/api/openstack/compute/flavor_access.py +++ b/nova/api/openstack/compute/flavor_access.py @@ -76,7 +76,7 @@ class FlavorActionController(wsgi.Controller): flavor = common.get_flavor(context, id) try: - if api_version_request.is_supported(req, min_version='2.7'): + if api_version_request.is_supported(req, '2.7'): if flavor.is_public: exp = _("Can not add access to a public flavor.") raise webob.exc.HTTPConflict(explanation=exp) diff --git a/nova/api/openstack/compute/flavors.py b/nova/api/openstack/compute/flavors.py index be950240d9bd..b600cd2e1db1 100644 --- a/nova/api/openstack/compute/flavors.py +++ b/nova/api/openstack/compute/flavors.py @@ -79,8 +79,7 @@ class FlavorsController(wsgi.Controller): is_public = vals.get('os-flavor-access:is_public', True) # The user can specify a description starting with microversion 2.55. - include_description = api_version_request.is_supported( - req, flavors_view.FLAVOR_DESCRIPTION_MICROVERSION) + include_description = api_version_request.is_supported(req, '2.55') description = vals.get('description') if include_description else None try: @@ -97,8 +96,7 @@ class FlavorsController(wsgi.Controller): raise webob.exc.HTTPConflict(explanation=err.format_message()) include_extra_specs = False - if api_version_request.is_supported( - req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION): + if api_version_request.is_supported(req, '2.61'): include_extra_specs = context.can( fes_policies.POLICY_ROOT % 'index', fatal=False) # NOTE(yikun): This empty extra_specs only for keeping consistent @@ -130,8 +128,7 @@ class FlavorsController(wsgi.Controller): raise webob.exc.HTTPNotFound(explanation=e.format_message()) include_extra_specs = False - if api_version_request.is_supported( - req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION): + if api_version_request.is_supported(req, '2.61'): include_extra_specs = context.can( fes_policies.POLICY_ROOT % 'index', fatal=False) return self._view_builder.show(req, flavor, include_description=True, @@ -157,11 +154,12 @@ class FlavorsController(wsgi.Controller): """Return all flavors in detail.""" context = req.environ['nova.context'] limited_flavors = self._get_flavors(req) + include_extra_specs = False - if api_version_request.is_supported( - req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION): + if api_version_request.is_supported(req, '2.61'): include_extra_specs = context.can( fes_policies.POLICY_ROOT % 'index', fatal=False) + return self._view_builder.detail( req, limited_flavors, include_extra_specs=include_extra_specs) @@ -180,12 +178,12 @@ class FlavorsController(wsgi.Controller): raise webob.exc.HTTPNotFound(explanation=e.format_message()) include_extra_specs = False - if api_version_request.is_supported( - req, flavors_view.FLAVOR_EXTRA_SPECS_MICROVERSION): + if api_version_request.is_supported(req, '2.61'): include_extra_specs = context.can( fes_policies.POLICY_ROOT % 'index', fatal=False) - include_description = api_version_request.is_supported( - req, flavors_view.FLAVOR_DESCRIPTION_MICROVERSION) + + include_description = api_version_request.is_supported(req, '2.55') + return self._view_builder.show( req, flavor, include_description=include_description, include_extra_specs=include_extra_specs) diff --git a/nova/api/openstack/compute/flavors_extraspecs.py b/nova/api/openstack/compute/flavors_extraspecs.py index eb68a937487f..74ad6ba3d77a 100644 --- a/nova/api/openstack/compute/flavors_extraspecs.py +++ b/nova/api/openstack/compute/flavors_extraspecs.py @@ -35,9 +35,7 @@ class FlavorExtraSpecsController(wsgi.Controller): return dict(extra_specs=flavor.extra_specs) def _check_extra_specs_value(self, req, specs): - validation_supported = api_version_request.is_supported( - req, min_version='2.86', - ) + validation_supported = api_version_request.is_supported(req, '2.86') for name, value in specs.items(): # NOTE(gmann): Max length for numeric value is being checked diff --git a/nova/api/openstack/compute/hypervisors.py b/nova/api/openstack/compute/hypervisors.py index 9ae93cd6a2df..65550ea1d5c3 100644 --- a/nova/api/openstack/compute/hypervisors.py +++ b/nova/api/openstack/compute/hypervisors.py @@ -53,8 +53,7 @@ class HypervisorsController(wsgi.Controller): ): alive = self.servicegroup_api.service_is_up(service) # The 2.53 microversion returns the compute node uuid rather than id. - uuid_for_id = api_version_request.is_supported( - req, min_version="2.53") + uuid_for_id = api_version_request.is_supported(req, "2.53") hyp_dict = { 'id': hypervisor.uuid if uuid_for_id else hypervisor.id, @@ -77,9 +76,7 @@ class HypervisorsController(wsgi.Controller): # The 2.88 microversion removed these fields, so only add them on older # microversions - if detail and api_version_request.is_supported( - req, max_version='2.87', - ): + if detail and not api_version_request.is_supported(req, '2.88'): for field in ( 'vcpus', 'memory_mb', 'local_gb', 'vcpus_used', 'memory_mb_used', 'local_gb_used', 'free_ram_mb', @@ -88,18 +85,16 @@ class HypervisorsController(wsgi.Controller): ): hyp_dict[field] = getattr(hypervisor, field) - if api_version_request.is_supported(req, max_version='2.27'): - hyp_dict['cpu_info'] = hypervisor.cpu_info - else: + if api_version_request.is_supported(req, '2.28'): if hypervisor.cpu_info: hyp_dict['cpu_info'] = jsonutils.loads(hypervisor.cpu_info) else: hyp_dict['cpu_info'] = {} + else: + hyp_dict['cpu_info'] = hypervisor.cpu_info # The 2.88 microversion also *added* the 'uptime' field to the response - if detail and api_version_request.is_supported( - req, min_version='2.88', - ): + if detail and api_version_request.is_supported(req, '2.88'): try: hyp_dict['uptime'] = self.host_api.get_host_uptime( req.environ['nova.context'], hypervisor.host) @@ -121,9 +116,7 @@ class HypervisorsController(wsgi.Controller): # The 2.75 microversion adds 'servers' field always in response. # Empty list if there are no servers on hypervisors and it is # requested in request. - elif with_servers and api_version_request.is_supported( - req, min_version='2.75', - ): + elif with_servers and api_version_request.is_supported(req, '2.75'): hyp_dict['servers'] = [] return hyp_dict @@ -152,7 +145,7 @@ class HypervisorsController(wsgi.Controller): # The 2.53 microversion moves the search and servers routes into # GET /os-hypervisors and GET /os-hypervisors/detail with query # parameters. - if api_version_request.is_supported(req, min_version="2.53"): + if api_version_request.is_supported(req, "2.53"): hypervisor_match = req.GET.get('hypervisor_hostname_pattern') with_servers = strutils.bool_from_string( req.GET.get('with_servers', False), strict=True) @@ -295,7 +288,7 @@ class HypervisorsController(wsgi.Controller): :raises: webob.exc.HTTPNotFound if the requested microversion is less than 2.53 and the id is not an integer. """ - if api_version_request.is_supported(req, min_version="2.53"): + if api_version_request.is_supported(req, "2.53"): if not uuidutils.is_uuid_like(hypervisor_id): msg = _('Invalid uuid %s') % hypervisor_id raise webob.exc.HTTPBadRequest(explanation=msg) diff --git a/nova/api/openstack/compute/instance_actions.py b/nova/api/openstack/compute/instance_actions.py index 2d5e05215cc0..19c12a372f3d 100644 --- a/nova/api/openstack/compute/instance_actions.py +++ b/nova/api/openstack/compute/instance_actions.py @@ -72,7 +72,7 @@ class InstanceActionsController(wsgi.Controller): return event def _get_instance(self, req, context, server_id): - if not api_version_request.is_supported(req, min_version="2.21"): + if not api_version_request.is_supported(req, '2.21'): return common.get_instance(self.compute_api, context, server_id) with utils.temporary_mutation(context, read_deleted='yes'): @@ -119,7 +119,7 @@ class InstanceActionsController(wsgi.Controller): except exception.MarkerNotFound as e: raise exc.HTTPBadRequest(explanation=e.format_message()) - if api_version_request.is_supported(req, min_version="2.58"): + if api_version_request.is_supported(req, '2.58'): actions = [self._format_action(action, ACTION_KEYS_V258) for action in actions_raw] else: @@ -150,7 +150,7 @@ class InstanceActionsController(wsgi.Controller): raise exc.HTTPNotFound(explanation=msg) action_id = action['id'] - if api_version_request.is_supported(req, min_version="2.58"): + if api_version_request.is_supported(req, '2.58'): action = self._format_action(action, ACTION_KEYS_V258) else: action = self._format_action(action, ACTION_KEYS) diff --git a/nova/api/openstack/compute/lock_server.py b/nova/api/openstack/compute/lock_server.py index b44675d68fdb..63a040ab0723 100644 --- a/nova/api/openstack/compute/lock_server.py +++ b/nova/api/openstack/compute/lock_server.py @@ -41,8 +41,10 @@ class LockServerController(wsgi.Controller): target={'user_id': instance.user_id, 'project_id': instance.project_id}) reason = None - if (api_version_request.is_supported(req, min_version='2.73') and - body['lock'] is not None): + if ( + api_version_request.is_supported(req, '2.73') and + body['lock'] is not None + ): reason = body['lock'].get('locked_reason') self.compute_api.lock(context, instance, reason=reason) diff --git a/nova/api/openstack/compute/migrate_server.py b/nova/api/openstack/compute/migrate_server.py index f23f63ddc3ed..cb8a9b0c2990 100644 --- a/nova/api/openstack/compute/migrate_server.py +++ b/nova/api/openstack/compute/migrate_server.py @@ -48,8 +48,10 @@ class MigrateServerController(wsgi.Controller): instance = common.get_instance(self.compute_api, context, id, expected_attrs=['flavor', 'services']) host_name = None - if (api_version_request.is_supported(req, min_version='2.56') and - body['migrate'] is not None): + if ( + api_version_request.is_supported(req, '2.56') and + body['migrate'] is not None + ): host_name = body['migrate'].get('host') if host_name: @@ -111,10 +113,10 @@ class MigrateServerController(wsgi.Controller): host = body["os-migrateLive"]["host"] block_migration = body["os-migrateLive"]["block_migration"] force = None - async_ = api_version_request.is_supported(req, min_version='2.34') - if api_version_request.is_supported(req, min_version='2.30'): + async_ = api_version_request.is_supported(req, '2.34') + if api_version_request.is_supported(req, '2.30'): force = self._get_force_param_for_live_migration(body, host) - if api_version_request.is_supported(req, min_version='2.25'): + if api_version_request.is_supported(req, '2.25'): if block_migration == 'auto': block_migration = None else: diff --git a/nova/api/openstack/compute/server_diagnostics.py b/nova/api/openstack/compute/server_diagnostics.py index 56a1c33873fa..755cfeaf9319 100644 --- a/nova/api/openstack/compute/server_diagnostics.py +++ b/nova/api/openstack/compute/server_diagnostics.py @@ -42,7 +42,7 @@ class ServerDiagnosticsController(wsgi.Controller): target={'project_id': instance.project_id}) try: - if api_version_request.is_supported(req, min_version='2.48'): + if api_version_request.is_supported(req, '2.48'): diagnostics = self.compute_api.get_instance_diagnostics( context, instance) return self._view_builder.instance_diagnostics(diagnostics) diff --git a/nova/api/openstack/compute/server_groups.py b/nova/api/openstack/compute/server_groups.py index b8c906552f29..5c2bfad7bdba 100644 --- a/nova/api/openstack/compute/server_groups.py +++ b/nova/api/openstack/compute/server_groups.py @@ -94,7 +94,7 @@ class ServerGroupController(wsgi.Controller): server_group = {} server_group['id'] = group.uuid server_group['name'] = group.name - if api_version_request.is_supported(req, min_version='2.64'): + if api_version_request.is_supported(req, '2.64'): server_group['policy'] = group.policy server_group['rules'] = group.rules else: @@ -109,7 +109,7 @@ class ServerGroupController(wsgi.Controller): server_group['members'] = members # Add project id information to the response data for # API version v2.13 - if api_version_request.is_supported(req, min_version="2.13"): + if api_version_request.is_supported(req, "2.13"): server_group['project_id'] = group.project_id server_group['user_id'] = group.user_id return server_group diff --git a/nova/api/openstack/compute/server_shares.py b/nova/api/openstack/compute/server_shares.py index f054623ee7cd..32d455914438 100644 --- a/nova/api/openstack/compute/server_shares.py +++ b/nova/api/openstack/compute/server_shares.py @@ -94,7 +94,7 @@ class ServerSharesController(wsgi.Controller): @wsgi.Controller.api_version("2.97") @wsgi.response(201) @wsgi.expected_errors((400, 403, 404, 409)) - @validation.schema(schema.create, min_version='2.97') + @validation.schema(schema.create, '2.97') @validation.response_body_schema(schema.show_response) def create(self, req, server_id, body): def _try_create_share_mapping(context, share_mapping): diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index 5c1617e7fb83..166f089c9de6 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -146,8 +146,7 @@ class ServersController(wsgi.Controller): @staticmethod def _is_cell_down_supported(req, search_opts): - cell_down_support = api_version_request.is_supported( - req, min_version='2.69') + cell_down_support = api_version_request.is_supported(req, '2.69') if cell_down_support: # NOTE(tssurya): Minimal constructs would be returned from the down @@ -200,7 +199,7 @@ class ServersController(wsgi.Controller): states = common.task_and_vm_state_from_status(statuses) vm_state, task_state = states if not vm_state and not task_state: - if api_version_request.is_supported(req, min_version='2.38'): + if api_version_request.is_supported(req, '2.38'): msg = _('Invalid status value') raise exc.HTTPBadRequest(explanation=msg) @@ -264,7 +263,7 @@ class ServersController(wsgi.Controller): msg = _("Only administrators may list deleted instances") raise exc.HTTPForbidden(explanation=msg) - if api_version_request.is_supported(req, min_version='2.26'): + if api_version_request.is_supported(req, '2.26'): for tag_filter in TAG_SEARCH_FILTERS: if tag_filter in search_opts: search_opts[tag_filter] = search_opts[ @@ -301,7 +300,7 @@ class ServersController(wsgi.Controller): limit, marker = common.get_limit_and_marker(req) sort_keys, sort_dirs = common.get_sort_params(req.params) blacklist = schema.SERVER_LIST_IGNORE_SORT_KEY - if api_version_request.is_supported(req, min_version='2.73'): + if api_version_request.is_supported(req, '2.73'): blacklist = schema.SERVER_LIST_IGNORE_SORT_KEY_V273 sort_keys, sort_dirs = remove_invalid_sort_keys( context, sort_keys, sort_dirs, blacklist, ('host', 'node')) @@ -462,10 +461,8 @@ class ServersController(wsgi.Controller): def show(self, req, id): """Returns server details by server id.""" context = req.environ['nova.context'] - cell_down_support = api_version_request.is_supported( - req, min_version='2.69') - show_server_groups = api_version_request.is_supported( - req, min_version='2.71') + cell_down_support = api_version_request.is_supported(req, '2.69') + show_server_groups = api_version_request.is_supported(req, '2.71') instance = self._get_server( context, req, id, is_detail=True, @@ -687,10 +684,10 @@ class ServersController(wsgi.Controller): password = self._get_server_admin_password(server_dict) name = common.normalize_name(server_dict['name']) description = name - if api_version_request.is_supported(req, min_version='2.19'): + if api_version_request.is_supported(req, '2.19'): description = server_dict.get('description') hostname = None - if api_version_request.is_supported(req, min_version='2.90'): + if api_version_request.is_supported(req, '2.90'): hostname = server_dict.get('hostname') # Arguments to be passed to instance create function @@ -731,7 +728,7 @@ class ServersController(wsgi.Controller): availability_zone = server_dict.pop("availability_zone", None) - if api_version_request.is_supported(req, min_version='2.52'): + if api_version_request.is_supported(req, '2.52'): create_kwargs['tags'] = server_dict.get('tags') helpers.translate_attributes(helpers.CREATE, @@ -763,7 +760,7 @@ class ServersController(wsgi.Controller): availability_zone = self._validate_host_availability_zone( context, availability_zone, host) - if api_version_request.is_supported(req, min_version='2.74'): + if api_version_request.is_supported(req, '2.74'): self._process_hosts_for_create(context, target, server_dict, create_kwargs, host, node) @@ -919,8 +916,7 @@ class ServersController(wsgi.Controller): ctxt.can(server_policies.SERVERS % 'update', target={'user_id': instance.user_id, 'project_id': instance.project_id}) - show_server_groups = api_version_request.is_supported( - req, min_version='2.71') + show_server_groups = api_version_request.is_supported(req, '2.71') server = body['server'] @@ -943,8 +939,7 @@ class ServersController(wsgi.Controller): # NOTE(gmann): Starting from microversion 2.75, PUT and Rebuild # API response will show all attributes like GET /servers API. - show_all_attributes = api_version_request.is_supported( - req, min_version='2.75') + show_all_attributes = api_version_request.is_supported(req, '2.75') extend_address = show_all_attributes show_AZ = show_all_attributes show_config_drive = show_all_attributes @@ -1222,22 +1217,21 @@ class ServersController(wsgi.Controller): helpers.translate_attributes(helpers.REBUILD, rebuild_dict, kwargs) if ( - api_version_request.is_supported(req, min_version='2.54') and + api_version_request.is_supported(req, '2.54') and 'key_name' in rebuild_dict ): kwargs['key_name'] = rebuild_dict.get('key_name') # If user_data is not specified, we don't include it in kwargs because # we don't want to overwrite the existing user_data. - include_user_data = api_version_request.is_supported( - req, min_version='2.57') + include_user_data = api_version_request.is_supported(req, '2.57') if include_user_data and 'user_data' in rebuild_dict: kwargs['user_data'] = rebuild_dict['user_data'] # Skip policy check for 'rebuild:trusted_certs' if no trusted # certificate IDs were provided. if ( - api_version_request.is_supported(req, min_version='2.63') and + api_version_request.is_supported(req, '2.63') and # Note that this is different from server create since with # rebuild a user can unset/reset the trusted certs by # specifying trusted_image_certificates=None, similar to @@ -1250,12 +1244,12 @@ class ServersController(wsgi.Controller): target=target) if ( - api_version_request.is_supported(req, min_version='2.90') and + api_version_request.is_supported(req, '2.90') and 'hostname' in rebuild_dict ): kwargs['hostname'] = rebuild_dict['hostname'] - if api_version_request.is_supported(req, min_version='2.93'): + if api_version_request.is_supported(req, '2.93'): kwargs['reimage_boot_volume'] = True for request_attribute, instance_attribute in attr_map.items(): @@ -1307,15 +1301,12 @@ class ServersController(wsgi.Controller): # NOTE(liuyulong): set the new key_name for the API response. # from microversion 2.54 onwards. - show_keypair = api_version_request.is_supported( - req, min_version='2.54') - show_server_groups = api_version_request.is_supported( - req, min_version='2.71') + show_keypair = api_version_request.is_supported(req, '2.54') + show_server_groups = api_version_request.is_supported(req, '2.71') # NOTE(gmann): Starting from microversion 2.75, PUT and Rebuild # API response will show all attributes like GET /servers API. - show_all_attributes = api_version_request.is_supported( - req, min_version='2.75') + show_all_attributes = api_version_request.is_supported(req, '2.75') extend_address = show_all_attributes show_AZ = show_all_attributes show_config_drive = show_all_attributes @@ -1379,9 +1370,7 @@ class ServersController(wsgi.Controller): metadata = entity.get('metadata', {}) # Starting from microversion 2.39 we don't check quotas on createImage - if api_version_request.is_supported( - req, max_version= - api_version_request.MAX_IMAGE_META_PROXY_API_VERSION): + if not api_version_request.is_supported(req, '2.39'): common.check_img_metadata_properties_quota(context, metadata) bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( @@ -1443,20 +1432,20 @@ class ServersController(wsgi.Controller): # probably not trivial. opt_list = ('reservation_id', 'name', 'status', 'image', 'flavor', 'ip', 'changes-since', 'all_tenants') - if api_version_request.is_supported(req, min_version='2.5'): + if api_version_request.is_supported(req, '2.5'): opt_list += ('ip6',) - if api_version_request.is_supported(req, min_version='2.26'): + if api_version_request.is_supported(req, '2.26'): opt_list += TAG_SEARCH_FILTERS - if api_version_request.is_supported(req, min_version='2.66'): + if api_version_request.is_supported(req, '2.66'): opt_list += ('changes-before',) - if api_version_request.is_supported(req, min_version='2.73'): + if api_version_request.is_supported(req, '2.73'): opt_list += ('locked',) - if api_version_request.is_supported(req, min_version='2.83'): + if api_version_request.is_supported(req, '2.83'): opt_list += ('availability_zone', 'config_drive', 'key_name', 'created_at', 'launched_at', 'terminated_at', 'power_state', 'task_state', 'vm_state', 'progress', 'user_id',) - if api_version_request.is_supported(req, min_version='2.90'): + if api_version_request.is_supported(req, '2.90'): opt_list += ('hostname',) return opt_list diff --git a/nova/api/openstack/compute/services.py b/nova/api/openstack/compute/services.py index b37e947cf435..25bfa171459a 100644 --- a/nova/api/openstack/compute/services.py +++ b/nova/api/openstack/compute/services.py @@ -58,8 +58,7 @@ class ServiceController(wsgi.Controller): context = req.environ['nova.context'] - cell_down_support = api_version_request.is_supported( - req, min_version='2.69') + cell_down_support = api_version_request.is_supported(req, '2.69') _services = [ s @@ -98,8 +97,7 @@ class ServiceController(wsgi.Controller): active = 'disabled' updated_time = self.servicegroup_api.get_updated_time(svc) - uuid_for_id = api_version_request.is_supported( - req, min_version='2.53') + uuid_for_id = api_version_request.is_supported(req, '2.53') if 'availability_zone' not in svc: # The service wasn't loaded with the AZ so we need to do it here. @@ -127,8 +125,7 @@ class ServiceController(wsgi.Controller): def _get_services_list(self, req, additional_fields=()): _services = self._get_services(req) - cell_down_support = api_version_request.is_supported( - req, min_version='2.69') + cell_down_support = api_version_request.is_supported(req, '2.69') return [self._get_service_detail(svc, additional_fields, req, cell_down_support=cell_down_support) for svc in _services] @@ -248,7 +245,7 @@ class ServiceController(wsgi.Controller): context = req.environ['nova.context'] context.can(services_policies.BASE_POLICY_NAME % 'delete', target={}) - if api_version_request.is_supported(req, min_version='2.53'): + if api_version_request.is_supported(req, '2.53'): if not uuidutils.is_uuid_like(id): msg = _('Invalid uuid %s') % id raise webob.exc.HTTPBadRequest(explanation=msg) @@ -378,7 +375,7 @@ class ServiceController(wsgi.Controller): """ context = req.environ['nova.context'] context.can(services_policies.BASE_POLICY_NAME % 'list', target={}) - if api_version_request.is_supported(req, min_version='2.11'): + if api_version_request.is_supported(req, '2.11'): _services = self._get_services_list(req, ['forced_down']) else: _services = self._get_services_list(req) @@ -401,7 +398,7 @@ class ServiceController(wsgi.Controller): path of the request to uniquely identify the service record on which to perform a given update, which is defined in the body of the request. """ - if api_version_request.is_supported(req, min_version='2.53'): + if api_version_request.is_supported(req, '2.53'): return self._update_v253(req, id, body) else: return self._update_v21(req, id, body) @@ -409,7 +406,7 @@ class ServiceController(wsgi.Controller): def _update_v21(self, req, id, body): context = req.environ['nova.context'] context.can(services_policies.BASE_POLICY_NAME % 'update', target={}) - if api_version_request.is_supported(req, min_version='2.11'): + if api_version_request.is_supported(req, '2.11'): actions = self.actions.copy() actions["force-down"] = self._forced_down else: diff --git a/nova/api/openstack/compute/views/flavors.py b/nova/api/openstack/compute/views/flavors.py index 1df4f093ba0f..aab7099caf7a 100644 --- a/nova/api/openstack/compute/views/flavors.py +++ b/nova/api/openstack/compute/views/flavors.py @@ -16,9 +16,6 @@ from nova.api.openstack import api_version_request from nova.api.openstack import common -FLAVOR_DESCRIPTION_MICROVERSION = '2.55' -FLAVOR_EXTRA_SPECS_MICROVERSION = '2.61' - class ViewBuilder(common.ViewBuilder): @@ -78,16 +75,14 @@ class ViewBuilder(common.ViewBuilder): def index(self, request, flavors): """Return the 'index' view of flavors.""" coll_name = self._collection_name - include_description = api_version_request.is_supported( - request, FLAVOR_DESCRIPTION_MICROVERSION) + include_description = api_version_request.is_supported(request, '2.55') return self._list_view(self.basic, request, flavors, coll_name, include_description=include_description) def detail(self, request, flavors, include_extra_specs=False): """Return the 'detail' view of flavors.""" coll_name = self._collection_name + '/detail' - include_description = api_version_request.is_supported( - request, FLAVOR_DESCRIPTION_MICROVERSION) + include_description = api_version_request.is_supported(request, '2.55') return self._list_view(self.show, request, flavors, coll_name, include_description=include_description, include_extra_specs=include_extra_specs) diff --git a/nova/api/openstack/compute/views/servers.py b/nova/api/openstack/compute/views/servers.py index 023669406eb5..d3be41f8b173 100644 --- a/nova/api/openstack/compute/views/servers.py +++ b/nova/api/openstack/compute/views/servers.py @@ -268,7 +268,7 @@ class ViewBuilder(common.ViewBuilder): # detail will pre-calculate this for us. If we're doing show, # then figure it out here. show_extra_specs = False - if api_version_request.is_supported(request, min_version='2.47'): + if api_version_request.is_supported(request, '2.47'): context = request.environ['nova.context'] show_extra_specs = context.can( servers_policies.SERVERS % 'show:flavor-extra-specs', @@ -330,11 +330,11 @@ class ViewBuilder(common.ViewBuilder): # attributes after v2.1. They are only in v2.1 for backward compat # with v2.0. server["server"]["OS-EXT-AZ:availability_zone"] = az or '' - if api_version_request.is_supported(request, min_version='2.96'): + if api_version_request.is_supported(request, '2.96'): pinned_az = self._get_pinned_az(context, instance, provided_az) server['server']['pinned_availability_zone'] = pinned_az - if api_version_request.is_supported(request, min_version='2.100'): + if api_version_request.is_supported(request, '2.100'): server['server']['scheduler_hints'] = ( self._get_scheduler_hints( context, instance, provided_sched_hints)) @@ -364,7 +364,7 @@ class ViewBuilder(common.ViewBuilder): if show_extended_attr: properties = ['host', 'name', 'node'] - if api_version_request.is_supported(request, min_version='2.3'): + if api_version_request.is_supported(request, '2.3'): # NOTE(mriedem): These will use the OS-EXT-SRV-ATTR prefix # below and that's OK for microversion 2.3 which is being # compatible with v2.0 for the ec2 API split out from Nova. @@ -408,7 +408,7 @@ class ViewBuilder(common.ViewBuilder): # for new attributes after v2.1. They are only in v2.1 for backward # compat with v2.0. add_delete_on_termination = api_version_request.is_supported( - request, min_version='2.3') + request, '2.3') if bdms is None: bdms = objects.BlockDeviceMappingList.bdms_by_instance_uuid( context, [instance["uuid"]]) @@ -416,7 +416,7 @@ class ViewBuilder(common.ViewBuilder): bdms, add_delete_on_termination) - if api_version_request.is_supported(request, min_version='2.16'): + if api_version_request.is_supported(request, '2.16'): if show_host_status is None: unknown_only = self._get_host_status_unknown_only( context, instance) @@ -435,22 +435,22 @@ class ViewBuilder(common.ViewBuilder): host_status == fields.HostStatus.UNKNOWN): server["server"]['host_status'] = host_status - if api_version_request.is_supported(request, min_version="2.9"): + if api_version_request.is_supported(request, "2.9"): server["server"]["locked"] = (True if instance["locked_by"] else False) - if api_version_request.is_supported(request, min_version="2.73"): + if api_version_request.is_supported(request, "2.73"): server["server"]["locked_reason"] = (instance.system_metadata.get( "locked_reason")) - if api_version_request.is_supported(request, min_version="2.19"): + if api_version_request.is_supported(request, "2.19"): server["server"]["description"] = instance.get( "display_description") - if api_version_request.is_supported(request, min_version="2.26"): + if api_version_request.is_supported(request, "2.26"): server["server"]["tags"] = [t.tag for t in instance.tags] - if api_version_request.is_supported(request, min_version="2.63"): + if api_version_request.is_supported(request, "2.63"): trusted_certs = None if instance.trusted_certs: trusted_certs = instance.trusted_certs.ids @@ -458,7 +458,7 @@ class ViewBuilder(common.ViewBuilder): # TODO(stephenfin): Remove this check once we remove the # OS-EXT-SRV-ATTR:hostname policy checks from the policy is Y or later - if api_version_request.is_supported(request, min_version='2.90'): + if api_version_request.is_supported(request, '2.90'): # API 2.90 made this field visible to non-admins, but we only show # it if it's not already added if not show_extended_attr: @@ -482,7 +482,7 @@ class ViewBuilder(common.ViewBuilder): coll_name = self._collection_name + '/detail' context = request.environ['nova.context'] - if api_version_request.is_supported(request, min_version='2.47'): + if api_version_request.is_supported(request, '2.47'): # Determine if we should show extra_specs in the inlined flavor # once before we iterate the list of instances show_extra_specs = context.can( @@ -510,7 +510,7 @@ class ViewBuilder(common.ViewBuilder): bdms=bdms, cell_down_support=cell_down_support) - if api_version_request.is_supported(request, min_version='2.16'): + if api_version_request.is_supported(request, '2.16'): unknown_only = self._get_host_status_unknown_only(context) # If we're not allowed by policy to show host status at all, don't # bother requesting instance host status from the compute API. @@ -548,7 +548,7 @@ class ViewBuilder(common.ViewBuilder): req_specs = None req_specs_dict = {} sched_hints_dict = {} - if api_version_request.is_supported(request, min_version='2.96'): + if api_version_request.is_supported(request, '2.96'): context = request.environ['nova.context'] instance_uuids = [s.uuid for s in servers] req_specs = objects.RequestSpec.get_by_instance_uuids( @@ -556,7 +556,7 @@ class ViewBuilder(common.ViewBuilder): req_specs_dict.update({req.instance_uuid: req.availability_zone for req in req_specs if req.availability_zone is not None}) - if api_version_request.is_supported(request, min_version='2.100'): + if api_version_request.is_supported(request, '2.100'): sched_hints_dict.update({ req.instance_uuid: req.scheduler_hints for req in req_specs @@ -633,7 +633,7 @@ class ViewBuilder(common.ViewBuilder): }], } - if api_version_request.is_supported(request, min_version='2.98'): + if api_version_request.is_supported(request, '2.98'): image_props = {} for key, value in instance.system_metadata.items(): if key.startswith(utils.SM_IMAGE_PROP_PREFIX): @@ -668,7 +668,7 @@ class ViewBuilder(common.ViewBuilder): "from the DB", instance=instance) return {} - if api_version_request.is_supported(request, min_version="2.47"): + if api_version_request.is_supported(request, "2.47"): return self._get_flavor_dict(request, flavor, show_extra_specs) flavor_id = flavor["flavorid"] diff --git a/nova/api/openstack/compute/volumes.py b/nova/api/openstack/compute/volumes.py index 3f5deaa05a40..1ae4cf98da2c 100644 --- a/nova/api/openstack/compute/volumes.py +++ b/nova/api/openstack/compute/volumes.py @@ -271,7 +271,7 @@ def _translate_attachment_detail_view( def _check_request_version(req, min_version, method, server_id, server_state): - if not api_version_request.is_supported(req, min_version=min_version): + if not api_version_request.is_supported(req, min_version): exc_inv = exception.InstanceInvalidState( attr='vm_state', instance_uuid=server_id, @@ -496,8 +496,7 @@ class VolumeAttachmentController(wsgi.Controller): @wsgi.response(202) @wsgi.expected_errors((400, 404, 409)) @validation.schema(volumes_schema.update_volume_attachment, '2.0', '2.84') - @validation.schema(volumes_schema.update_volume_attachment_v285, - min_version='2.85') + @validation.schema(volumes_schema.update_volume_attachment_v285, '2.85') def update(self, req, server_id, id, body): context = req.environ['nova.context'] instance = common.get_instance(self.compute_api, context, server_id) diff --git a/nova/tests/unit/api/openstack/compute/test_servers.py b/nova/tests/unit/api/openstack/compute/test_servers.py index 745bc6f891b9..72c6fba127f3 100644 --- a/nova/tests/unit/api/openstack/compute/test_servers.py +++ b/nova/tests/unit/api/openstack/compute/test_servers.py @@ -8104,10 +8104,9 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest): self.view_builder = views.servers.ViewBuilder() self.ctxt = context.RequestContext('fake', self.project_id) - def fake_is_supported(req, min_version="2.1", max_version="2.69"): - return (fakes.api_version.APIVersionRequest(max_version) >= - req.api_version_request >= - fakes.api_version.APIVersionRequest(min_version)) + def fake_is_supported(req, version="2.1"): + return (req.api_version_request >= + fakes.api_version.APIVersionRequest(version)) self.stub_out('nova.api.openstack.api_version_request.is_supported', fake_is_supported) diff --git a/nova/tests/unit/api/openstack/test_api_version_request.py b/nova/tests/unit/api/openstack/test_api_version_request.py index 5b6ac478d718..357a59943ab5 100644 --- a/nova/tests/unit/api/openstack/test_api_version_request.py +++ b/nova/tests/unit/api/openstack/test_api_version_request.py @@ -127,40 +127,9 @@ class APIVersionRequestTests(test.NoDBTestCase): self.assertRaises(ValueError, api_version_request.APIVersionRequest().get_string) - def test_is_supported_min_version(self): + def test_is_supported(self): req = fakes.HTTPRequest.blank(self.base_path, version='2.5') - self.assertTrue(api_version_request.is_supported( - req, min_version='2.4')) - self.assertTrue(api_version_request.is_supported( - req, min_version='2.5')) - self.assertFalse(api_version_request.is_supported( - req, min_version='2.6')) - - def test_is_supported_max_version(self): - req = fakes.HTTPRequest.blank(self.base_path, version='2.5') - - self.assertFalse(api_version_request.is_supported( - req, max_version='2.4')) - self.assertTrue(api_version_request.is_supported( - req, max_version='2.5')) - self.assertTrue(api_version_request.is_supported( - req, max_version='2.6')) - - def test_is_supported_min_and_max_version(self): - req = fakes.HTTPRequest.blank(self.base_path, version='2.5') - - self.assertFalse(api_version_request.is_supported( - req, min_version='2.3', max_version='2.4')) - self.assertTrue(api_version_request.is_supported( - req, min_version='2.3', max_version='2.5')) - self.assertTrue(api_version_request.is_supported( - req, min_version='2.3', max_version='2.7')) - self.assertTrue(api_version_request.is_supported( - req, min_version='2.5', max_version='2.7')) - self.assertFalse(api_version_request.is_supported( - req, min_version='2.6', max_version='2.7')) - self.assertTrue(api_version_request.is_supported( - req, min_version='2.5', max_version='2.5')) - self.assertFalse(api_version_request.is_supported( - req, min_version='2.10', max_version='2.1')) + self.assertTrue(api_version_request.is_supported(req, '2.4')) + self.assertTrue(api_version_request.is_supported(req, '2.5')) + self.assertFalse(api_version_request.is_supported(req, '2.6'))