api: Stop using wsgi.Controller.api_version to switch between API versions

This obscures the purpose of the APIs and makes the code harder to read.
It also does not play nice with our schema checks by creating multiple
potential functions to check. We're already being pretty inconsistent in
how we do versioning like this so simply standardise on another
approach, namely checking in the function.

Note that there are docs that need updating here, but we're leaving that
to a separate PR that will also remove this method in favour of a new,
much simpler method.

Change-Id: Ia5e4c6cadb6c88ccdf7e89566573f1f89087fbe5
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane
2025-03-27 12:12:09 +00:00
parent 89977c3661
commit d73a0861f8
12 changed files with 330 additions and 453 deletions

View File

@@ -15,6 +15,7 @@
import webob import webob
from nova.api.openstack import api_version_request
from nova.api.openstack.compute.schemas import console_auth_tokens as schema from nova.api.openstack.compute.schemas import console_auth_tokens as schema
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.api import validation from nova.api import validation
@@ -29,6 +30,34 @@ CONF = nova.conf.CONF
class ConsoleAuthTokensController(wsgi.Controller): class ConsoleAuthTokensController(wsgi.Controller):
@wsgi.expected_errors((400, 401, 404), '2.1', '2.30')
@wsgi.expected_errors((400, 404), '2.31', '2.98')
@wsgi.expected_errors((400, 404), '2.99')
@validation.query_schema(schema.show_query, '2.1', '2.98')
@validation.query_schema(schema.show_query_v299, '2.99')
# NOTE(stephenfin): Technically this will never return a response now for
# microversion <= 2.30, (as an exception will be raised instead) but we use
# the same schema for documentation purposes
@validation.response_body_schema(schema.show_response, '2.1', '2.98')
@validation.response_body_schema(schema.show_response_v299, '2.99')
def show(self, req, id):
"""Show console auth token.
Until microversion 2.30, this API was available only for the rdp-html5
console type which has been removed along with the HyperV driver in the
Nova 29.0.0 (Caracal) release. As a result, we now return a HTTP 400
error for microversion <= 2.30. Starting from 2.31 microversion, this
API works for all the other supported console types.
"""
if not api_version_request.is_supported(req, '2.31'):
raise webob.exc.HTTPBadRequest()
include_tls_port = False
if api_version_request.is_supported(req, '2.99'):
include_tls_port = True
return self._show(req, id, include_tls_port=include_tls_port)
def _show(self, req, id, include_tls_port=False): def _show(self, req, id, include_tls_port=False):
"""Checks a console auth token and returns the related connect info.""" """Checks a console auth token and returns the related connect info."""
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -70,36 +99,3 @@ class ConsoleAuthTokensController(wsgi.Controller):
retval['console']['tls_port'] = connect_info.tls_port retval['console']['tls_port'] = connect_info.tls_port
return retval return retval
@wsgi.Controller.api_version("2.1", "2.30")
@wsgi.expected_errors((400, 401, 404))
@validation.query_schema(schema.show_query)
# NOTE(stephenfin): Technically this will never return a response now (as
# an exception will be raised instead) but we use the same schema for
# documentation purposes
@validation.response_body_schema(schema.show_response)
def show(self, req, id):
"""Until microversion 2.30, this API was available only for the
rdp-html5 console type which has been removed along with the HyperV
driver in the Nova 29.0.0 (Caracal) release. As this method is for
microversion <= 2.30, it will return an http 400 error. Starting
from 2.31 microversion, this API works for all the supported
console types that are handled by the separate show method
defined below.
"""
raise webob.exc.HTTPBadRequest()
@wsgi.Controller.api_version("2.31") # noqa
@wsgi.Controller.api_version("2.31", "2.98") # noqa
@wsgi.expected_errors((400, 404))
@validation.query_schema(schema.show_query)
@validation.response_body_schema(schema.show_response)
def show(self, req, id): # noqa
return self._show(req, id, include_tls_port=False)
@wsgi.Controller.api_version("2.99") # noqa
@wsgi.expected_errors((400, 404))
@validation.query_schema(schema.show_query_v299)
@validation.response_body_schema(schema.show_response_v299)
def show(self, req, id): # noqa
return self._show(req, id, include_tls_port=True)

View File

@@ -23,7 +23,7 @@ import webob.exc
from nova.api.openstack import api_version_request from nova.api.openstack import api_version_request
from nova.api.openstack import common from nova.api.openstack import common
from nova.api.openstack.compute.schemas import hypervisors as hyper_schema from nova.api.openstack.compute.schemas import hypervisors as schema
from nova.api.openstack.compute.views import hypervisors as hyper_view from nova.api.openstack.compute.views import hypervisors as hyper_view
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.api import validation from nova.api import validation
@@ -223,31 +223,29 @@ class HypervisorsController(wsgi.Controller):
hypervisors_dict['hypervisors_links'] = hypervisors_links hypervisors_dict['hypervisors_links'] = hypervisors_links
return hypervisors_dict return hypervisors_dict
@wsgi.Controller.api_version("2.53") @wsgi.expected_errors((), '2.1', '2.32')
@wsgi.expected_errors((400, 404)) @wsgi.expected_errors(400, '2.33', '2.52')
@validation.query_schema(hyper_schema.index_query_v253, "2.53") @wsgi.expected_errors((400, 404), '2.53')
@validation.query_schema(schema.index_query, '2.1', '2.32')
@validation.query_schema(schema.index_query_v233, '2.33', '2.52')
@validation.query_schema(schema.index_query_v253, '2.53')
def index(self, req): def index(self, req):
"""Starting with the 2.53 microversion, the id field in the response """List hypervisors.
Starting with the 2.53 microversion, the id field in the response
is the compute_nodes.uuid value. Also, the search and servers routes is the compute_nodes.uuid value. Also, the search and servers routes
are superseded and replaced with query parameters for listing are superseded and replaced with query parameters for listing
hypervisors by a hostname pattern and whether or not to include hypervisors by a hostname pattern and whether or not to include
hosted servers in the response. hosted servers in the response.
""" """
limit, marker = common.get_limit_and_marker(req) limit = None
return self._index(req, limit=limit, marker=marker, links=True) marker = None
links = False
if api_version_request.is_supported(req, '2.33'):
limit, marker = common.get_limit_and_marker(req)
links = True
@wsgi.Controller.api_version("2.33", "2.52") # noqa return self._index(req, limit=limit, marker=marker, links=links)
@wsgi.expected_errors(400)
@validation.query_schema(hyper_schema.index_query_v233)
def index(self, req): # noqa
limit, marker = common.get_limit_and_marker(req)
return self._index(req, limit=limit, marker=marker, links=True)
@wsgi.Controller.api_version("2.1", "2.32") # noqa
@wsgi.expected_errors(())
@validation.query_schema(hyper_schema.index_query)
def index(self, req): # noqa
return self._index(req)
def _index(self, req, limit=None, marker=None, links=False): def _index(self, req, limit=None, marker=None, links=False):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -255,31 +253,29 @@ class HypervisorsController(wsgi.Controller):
return self._get_hypervisors(req, detail=False, limit=limit, return self._get_hypervisors(req, detail=False, limit=limit,
marker=marker, links=links) marker=marker, links=links)
@wsgi.Controller.api_version("2.53") @wsgi.expected_errors((), '2.1', '2.32')
@wsgi.expected_errors((400, 404)) @wsgi.expected_errors((400), '2.33', '2.52')
@validation.query_schema(hyper_schema.index_query_v253, "2.53") @wsgi.expected_errors((400, 404), '2.53')
@validation.query_schema(schema.index_query, '2.1', '2.32')
@validation.query_schema(schema.index_query_v233, '2.33', '2.52')
@validation.query_schema(schema.index_query_v253, '2.53')
def detail(self, req): def detail(self, req):
"""Starting with the 2.53 microversion, the id field in the response """List hypervisors with extra details.
Starting with the 2.53 microversion, the id field in the response
is the compute_nodes.uuid value. Also, the search and servers routes is the compute_nodes.uuid value. Also, the search and servers routes
are superseded and replaced with query parameters for listing are superseded and replaced with query parameters for listing
hypervisors by a hostname pattern and whether or not to include hypervisors by a hostname pattern and whether or not to include
hosted servers in the response. hosted servers in the response.
""" """
limit, marker = common.get_limit_and_marker(req) limit = None
return self._detail(req, limit=limit, marker=marker, links=True) marker = None
links = False
if api_version_request.is_supported(req, '2.33'):
limit, marker = common.get_limit_and_marker(req)
links = True
@wsgi.Controller.api_version("2.33", "2.52") # noqa return self._detail(req, limit=limit, marker=marker, links=links)
@wsgi.expected_errors((400))
@validation.query_schema(hyper_schema.index_query_v233)
def detail(self, req): # noqa
limit, marker = common.get_limit_and_marker(req)
return self._detail(req, limit=limit, marker=marker, links=True)
@wsgi.Controller.api_version("2.1", "2.32") # noqa
@wsgi.expected_errors(())
@validation.query_schema(hyper_schema.index_query)
def detail(self, req): # noqa
return self._detail(req)
def _detail(self, req, limit=None, marker=None, links=False): def _detail(self, req, limit=None, marker=None, links=False):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -311,25 +307,25 @@ class HypervisorsController(wsgi.Controller):
hypervisor_id) hypervisor_id)
raise webob.exc.HTTPNotFound(explanation=msg) raise webob.exc.HTTPNotFound(explanation=msg)
@wsgi.Controller.api_version("2.53") @wsgi.expected_errors(404, '2.1', '2.52')
@wsgi.expected_errors((400, 404)) @wsgi.expected_errors((400, 404), '2.53')
@validation.query_schema(hyper_schema.show_query_v253, "2.53") @validation.query_schema(schema.show_query, '2.1', '2.52')
@validation.query_schema(schema.show_query_v253, '2.53')
def show(self, req, id): def show(self, req, id):
"""The 2.53 microversion requires that the id is a uuid and as a result """Show a hypervisor.
The 2.53 microversion requires that the id is a uuid and as a result
it can also return a 400 response if an invalid uuid is passed. it can also return a 400 response if an invalid uuid is passed.
The 2.53 microversion also supports the with_servers query parameter The 2.53 microversion also supports the with_servers query parameter
to include a list of servers on the given hypervisor if requested. to include a list of servers on the given hypervisor if requested.
""" """
with_servers = strutils.bool_from_string( with_servers = False
req.GET.get('with_servers', False), strict=True) if api_version_request.is_supported(req, '2.53'):
return self._show(req, id, with_servers) with_servers = strutils.bool_from_string(
req.GET.get('with_servers', False), strict=True)
@wsgi.Controller.api_version("2.1", "2.52") # noqa F811 return self._show(req, id, with_servers=with_servers)
@wsgi.expected_errors(404)
@validation.query_schema(hyper_schema.show_query)
def show(self, req, id): # noqa
return self._show(req, id)
def _show(self, req, id, with_servers=False): def _show(self, req, id, with_servers=False):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -372,7 +368,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.87') @wsgi.Controller.api_version('2.1', '2.87')
@wsgi.expected_errors((400, 404, 501)) @wsgi.expected_errors((400, 404, 501))
@validation.query_schema(hyper_schema.uptime_query) @validation.query_schema(schema.uptime_query)
def uptime(self, req, id): def uptime(self, req, id):
"""Prior to microversion 2.88, you could retrieve a special version of """Prior to microversion 2.88, you could retrieve a special version of
the hypervisor detail view that included uptime. Starting in 2.88, this the hypervisor detail view that included uptime. Starting in 2.88, this
@@ -425,7 +421,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.52') @wsgi.Controller.api_version('2.1', '2.52')
@wsgi.expected_errors(404) @wsgi.expected_errors(404)
@validation.query_schema(hyper_schema.search_query) @validation.query_schema(schema.search_query)
def search(self, req, id): def search(self, req, id):
"""Prior to microversion 2.53 you could search for hypervisors by a """Prior to microversion 2.53 you could search for hypervisors by a
hostname pattern on a dedicated route. Starting with 2.53, searching hostname pattern on a dedicated route. Starting with 2.53, searching
@@ -464,7 +460,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.52') @wsgi.Controller.api_version('2.1', '2.52')
@wsgi.expected_errors(404) @wsgi.expected_errors(404)
@validation.query_schema(hyper_schema.servers_query) @validation.query_schema(schema.servers_query)
def servers(self, req, id): def servers(self, req, id):
"""Prior to microversion 2.53 you could search for hypervisors by a """Prior to microversion 2.53 you could search for hypervisors by a
hostname pattern and include servers on those hosts in the response on hostname pattern and include servers on those hosts in the response on
@@ -510,7 +506,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.87') @wsgi.Controller.api_version('2.1', '2.87')
@wsgi.expected_errors(()) @wsgi.expected_errors(())
@validation.query_schema(hyper_schema.statistics_query) @validation.query_schema(schema.statistics_query)
def statistics(self, req): def statistics(self, req):
"""Prior to microversion 2.88, you could get statistics for the """Prior to microversion 2.88, you could get statistics for the
hypervisor. Most of these are now accessible from placement and the few hypervisor. Most of these are now accessible from placement and the few

View File

@@ -19,8 +19,7 @@ from oslo_utils import timeutils
from nova.api.openstack import api_version_request from nova.api.openstack import api_version_request
from nova.api.openstack import common from nova.api.openstack import common
from nova.api.openstack.compute.schemas \ from nova.api.openstack.compute.schemas import instance_actions as schema
import instance_actions as schema_instance_actions
from nova.api.openstack.compute.views \ from nova.api.openstack.compute.views \
import instance_actions as instance_actions_view import instance_actions as instance_actions_view
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
@@ -72,58 +71,46 @@ class InstanceActionsController(wsgi.Controller):
event['details'] = event_raw['details'] event['details'] = event_raw['details']
return event return event
@wsgi.Controller.api_version("2.1", "2.20")
def _get_instance(self, req, context, server_id): def _get_instance(self, req, context, server_id):
return common.get_instance(self.compute_api, context, server_id) if not api_version_request.is_supported(req, min_version="2.21"):
return common.get_instance(self.compute_api, context, server_id)
@wsgi.Controller.api_version("2.21") # noqa
def _get_instance(self, req, context, server_id): # noqa
with utils.temporary_mutation(context, read_deleted='yes'): with utils.temporary_mutation(context, read_deleted='yes'):
return common.get_instance(self.compute_api, context, server_id) return common.get_instance(self.compute_api, context, server_id)
@wsgi.Controller.api_version("2.1", "2.57") @wsgi.expected_errors(404, "2.1", "2.57")
@wsgi.expected_errors(404) @wsgi.expected_errors((400, 404), "2.58")
@validation.query_schema(schema_instance_actions.list_query) @validation.query_schema(schema.list_query, "2.1", "2.57")
@validation.query_schema(schema.list_query_v258, "2.58", "2.65")
@validation.query_schema(schema.list_query_v266, "2.66")
def index(self, req, server_id): def index(self, req, server_id):
"""Returns the list of actions recorded for a given instance.""" """Returns the list of actions recorded for a given instance."""
context = req.environ["nova.context"] context = req.environ["nova.context"]
instance = self._get_instance(req, context, server_id) instance = self._get_instance(req, context, server_id)
context.can(ia_policies.BASE_POLICY_NAME % 'list', context.can(ia_policies.BASE_POLICY_NAME % 'list',
target={'project_id': instance.project_id}) target={'project_id': instance.project_id})
actions_raw = self.action_api.actions_get(context, instance)
actions = [self._format_action(action, ACTION_KEYS)
for action in actions_raw]
return {'instanceActions': actions}
@wsgi.Controller.api_version("2.58") # noqa if api_version_request.is_supported(req, '2.58'):
@wsgi.expected_errors((400, 404)) search_opts = {}
@validation.query_schema(schema_instance_actions.list_query_v266, search_opts.update(req.GET)
"2.66") if 'changes-since' in search_opts:
@validation.query_schema(schema_instance_actions.list_query_v258, search_opts['changes-since'] = timeutils.parse_isotime(
"2.58", "2.65") search_opts['changes-since'])
def index(self, req, server_id): # noqa
"""Returns the list of actions recorded for a given instance."""
context = req.environ["nova.context"]
instance = self._get_instance(req, context, server_id)
context.can(ia_policies.BASE_POLICY_NAME % 'list',
target={'project_id': instance.project_id})
search_opts = {}
search_opts.update(req.GET)
if 'changes-since' in search_opts:
search_opts['changes-since'] = timeutils.parse_isotime(
search_opts['changes-since'])
if 'changes-before' in search_opts: if 'changes-before' in search_opts:
search_opts['changes-before'] = timeutils.parse_isotime( search_opts['changes-before'] = timeutils.parse_isotime(
search_opts['changes-before']) search_opts['changes-before'])
changes_since = search_opts.get('changes-since') changes_since = search_opts.get('changes-since')
if (changes_since and search_opts['changes-before'] < if (changes_since and search_opts['changes-before'] <
search_opts['changes-since']): search_opts['changes-since']):
msg = _('The value of changes-since must be less than ' msg = _('The value of changes-since must be less than '
'or equal to changes-before.') 'or equal to changes-before.')
raise exc.HTTPBadRequest(explanation=msg) raise exc.HTTPBadRequest(explanation=msg)
limit, marker = common.get_limit_and_marker(req)
else:
limit, marker, search_opts = None, None, None
limit, marker = common.get_limit_and_marker(req)
try: try:
actions_raw = self.action_api.actions_get(context, instance, actions_raw = self.action_api.actions_get(context, instance,
limit=limit, limit=limit,
@@ -131,16 +118,25 @@ class InstanceActionsController(wsgi.Controller):
filters=search_opts) filters=search_opts)
except exception.MarkerNotFound as e: except exception.MarkerNotFound as e:
raise exc.HTTPBadRequest(explanation=e.format_message()) raise exc.HTTPBadRequest(explanation=e.format_message())
actions = [self._format_action(action, ACTION_KEYS_V258)
for action in actions_raw] if api_version_request.is_supported(req, min_version="2.58"):
actions = [self._format_action(action, ACTION_KEYS_V258)
for action in actions_raw]
else:
actions = [self._format_action(action, ACTION_KEYS)
for action in actions_raw]
actions_dict = {'instanceActions': actions} actions_dict = {'instanceActions': actions}
actions_links = self._view_builder.get_links(req, server_id, actions)
if actions_links: if api_version_request.is_supported(req, '2.58'):
actions_dict['links'] = actions_links if actions_links := self._view_builder.get_links(
req, server_id, actions
):
actions_dict['links'] = actions_links
return actions_dict return actions_dict
@wsgi.expected_errors(404) @wsgi.expected_errors(404)
@validation.query_schema(schema_instance_actions.show_query) @validation.query_schema(schema.show_query)
def show(self, req, server_id, id): def show(self, req, server_id, id):
"""Return data about the given instance action.""" """Return data about the given instance action."""
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -186,8 +182,7 @@ class InstanceActionsController(wsgi.Controller):
# NOTE(brinzhang): Event details are shown since microversion # NOTE(brinzhang): Event details are shown since microversion
# 2.84. # 2.84.
show_details = False show_details = False
support_v284 = api_version_request.is_supported(req, '2.84') if api_version_request.is_supported(req, '2.84'):
if support_v284:
show_details = context.can( show_details = context.can(
ia_policies.BASE_POLICY_NAME % 'events:details', ia_policies.BASE_POLICY_NAME % 'events:details',
target={'project_id': instance.project_id}, fatal=False) target={'project_id': instance.project_id}, fatal=False)

View File

@@ -40,67 +40,39 @@ class KeypairController(wsgi.Controller):
super(KeypairController, self).__init__() super(KeypairController, self).__init__()
self.api = compute_api.KeypairAPI() self.api = compute_api.KeypairAPI()
@wsgi.Controller.api_version("2.10") @wsgi.response(200, "2.0", "2.1")
@wsgi.response(201) @wsgi.response(201, "2.2")
@wsgi.expected_errors((400, 403, 409)) @wsgi.expected_errors((400, 403, 409))
@validation.schema(keypairs.create_v20, "2.0", "2.0")
@validation.schema(keypairs.create, "2.1", "2.1")
@validation.schema(keypairs.create_v22, "2.2", "2.9")
@validation.schema(keypairs.create_v210, "2.10", "2.91") @validation.schema(keypairs.create_v210, "2.10", "2.91")
@validation.schema(keypairs.create_v292, "2.92") @validation.schema(keypairs.create_v292, "2.92")
def create(self, req, body): def create(self, req, body):
"""Create or import keypair. """Create or import keypair.
Keypair generations are allowed until version 2.91. Sending name will generate a key and return private_key and
Afterwards, only imports are allowed. fingerprint. You can send a public_key to add an existing ssh key.
A policy check restricts users from creating keys for other users Starting in API microversion 2.2, keypairs will have the type ssh or
x509, specified by type.
params: keypair object with: Starting in API microversion 2.10, you can request a user if you are an
name (required) - string admin.
public_key (optional or required if >=2.92) - string
type (optional) - string Starting in API microversion 2.91, keypair generation is no longer
user_id (optional) - string permitted.
""" """
# handle optional user-id for admin only key_type = False
user_id = body['keypair'].get('user_id') if api_version_request.is_supported(req, '2.2'):
return self._create(req, body, key_type=True, user_id=user_id) key_type = True
@wsgi.Controller.api_version("2.2", "2.9") # noqa user_id = None
@wsgi.response(201) if api_version_request.is_supported(req, '2.10'):
@wsgi.expected_errors((400, 403, 409)) # handle optional user-id for admin only
@validation.schema(keypairs.create_v22) user_id = body['keypair'].get('user_id')
def create(self, req, body): # noqa
"""Create or import keypair.
Sending name will generate a key and return private_key return self._create(req, body, key_type=key_type, user_id=user_id)
and fingerprint.
Keypair will have the type ssh or x509, specified by type.
You can send a public_key to add an existing ssh/x509 key.
params: keypair object with:
name (required) - string
public_key (optional) - string
type (optional) - string
"""
return self._create(req, body, key_type=True)
@wsgi.Controller.api_version("2.1", "2.1") # noqa
@wsgi.expected_errors((400, 403, 409))
@validation.schema(keypairs.create_v20, "2.0", "2.0")
@validation.schema(keypairs.create, "2.1", "2.1")
def create(self, req, body): # noqa
"""Create or import keypair.
Sending name will generate a key and return private_key
and fingerprint.
You can send a public_key to add an existing ssh key.
params: keypair object with:
name (required) - string
public_key (optional) - string
"""
return self._create(req, body)
def _create(self, req, body, user_id=None, key_type=False): def _create(self, req, body, user_id=None, key_type=False):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -135,28 +107,23 @@ class KeypairController(wsgi.Controller):
private_key=return_priv_key, private_key=return_priv_key,
key_type=key_type) key_type=key_type)
@wsgi.Controller.api_version("2.1", "2.1") def _get_user_id(self, req):
@validation.query_schema(keypairs.delete_query_schema_v20) if 'user_id' in req.GET.keys():
@wsgi.response(202) user_id = req.GET.getall('user_id')[0]
return user_id
@wsgi.response(202, '2.0', '2.1')
@wsgi.response(204, '2.2')
@validation.query_schema(keypairs.delete_query_schema_v20, '2.1', '2.9')
@validation.query_schema(keypairs.delete_query_schema_v210, '2.10', '2.74')
@validation.query_schema(keypairs.delete_query_schema_v275, '2.75')
@wsgi.expected_errors(404) @wsgi.expected_errors(404)
def delete(self, req, id): def delete(self, req, id):
self._delete(req, id) user_id = None
if api_version_request.is_supported(req, '2.10'):
# handle optional user-id for admin only
user_id = self._get_user_id(req)
@wsgi.Controller.api_version("2.2", "2.9") # noqa
@validation.query_schema(keypairs.delete_query_schema_v20)
@wsgi.response(204)
@wsgi.expected_errors(404)
def delete(self, req, id): # noqa
self._delete(req, id)
@wsgi.Controller.api_version("2.10") # noqa
@validation.query_schema(keypairs.delete_query_schema_v275, '2.75')
@validation.query_schema(keypairs.delete_query_schema_v210, '2.10', '2.74')
@wsgi.response(204)
@wsgi.expected_errors(404)
def delete(self, req, id): # noqa
# handle optional user-id for admin only
user_id = self._get_user_id(req)
self._delete(req, id, user_id=user_id) self._delete(req, id, user_id=user_id)
def _delete(self, req, id, user_id=None): def _delete(self, req, id, user_id=None):
@@ -171,31 +138,21 @@ class KeypairController(wsgi.Controller):
except exception.KeypairNotFound as exc: except exception.KeypairNotFound as exc:
raise webob.exc.HTTPNotFound(explanation=exc.format_message()) raise webob.exc.HTTPNotFound(explanation=exc.format_message())
def _get_user_id(self, req): @validation.query_schema(keypairs.show_query_schema_v20, '2.0', '2.9')
if 'user_id' in req.GET.keys():
user_id = req.GET.getall('user_id')[0]
return user_id
@wsgi.Controller.api_version("2.10")
@validation.query_schema(keypairs.show_query_schema_v210, '2.10', '2.74') @validation.query_schema(keypairs.show_query_schema_v210, '2.10', '2.74')
@validation.query_schema(keypairs.show_query_schema_v275, '2.75') @validation.query_schema(keypairs.show_query_schema_v275, '2.75')
@wsgi.expected_errors(404) @wsgi.expected_errors(404)
def show(self, req, id): def show(self, req, id):
# handle optional user-id for admin only key_type = False
user_id = self._get_user_id(req) if api_version_request.is_supported(req, '2.2'):
return self._show(req, id, key_type=True, user_id=user_id) key_type = True
@wsgi.Controller.api_version("2.2", "2.9") # noqa user_id = None
@validation.query_schema(keypairs.show_query_schema_v20) if api_version_request.is_supported(req, '2.10'):
@wsgi.expected_errors(404) # handle optional user-id for admin only
def show(self, req, id): # noqa user_id = self._get_user_id(req)
return self._show(req, id, key_type=True)
@wsgi.Controller.api_version("2.1", "2.1") # noqa return self._show(req, id, key_type=key_type, user_id=user_id)
@validation.query_schema(keypairs.show_query_schema_v20)
@wsgi.expected_errors(404)
def show(self, req, id): # noqa
return self._show(req, id)
def _show(self, req, id, key_type=False, user_id=None): def _show(self, req, id, key_type=False, user_id=None):
"""Return data for the given key name.""" """Return data for the given key name."""
@@ -210,33 +167,29 @@ class KeypairController(wsgi.Controller):
raise webob.exc.HTTPNotFound(explanation=exc.format_message()) raise webob.exc.HTTPNotFound(explanation=exc.format_message())
return self._view_builder.show(keypair, key_type=key_type) return self._view_builder.show(keypair, key_type=key_type)
@wsgi.Controller.api_version("2.35") @validation.query_schema(keypairs.index_query_schema_v20, '2.0', '2.9')
@validation.query_schema(keypairs.index_query_schema_v275, '2.75') @validation.query_schema(keypairs.index_query_schema_v210, '2.10', '2.34')
@validation.query_schema(keypairs.index_query_schema_v235, '2.35', '2.74') @validation.query_schema(keypairs.index_query_schema_v235, '2.35', '2.74')
@wsgi.expected_errors(400) @validation.query_schema(keypairs.index_query_schema_v275, '2.75')
@wsgi.expected_errors((), '2.0', '2.9')
@wsgi.expected_errors(400, '2.10')
def index(self, req): def index(self, req):
user_id = self._get_user_id(req) key_type = False
return self._index(req, key_type=True, user_id=user_id, links=True) if api_version_request.is_supported(req, '2.2'):
key_type = True
@wsgi.Controller.api_version("2.10", "2.34") # noqa user_id = None
@validation.query_schema(keypairs.index_query_schema_v210) if api_version_request.is_supported(req, '2.10'):
@wsgi.expected_errors(()) # handle optional user-id for admin only
def index(self, req): # noqa user_id = self._get_user_id(req)
# handle optional user-id for admin only
user_id = self._get_user_id(req)
return self._index(req, key_type=True, user_id=user_id)
@wsgi.Controller.api_version("2.2", "2.9") # noqa links = False
@validation.query_schema(keypairs.index_query_schema_v20) if api_version_request.is_supported(req, '2.35'):
@wsgi.expected_errors(()) links = True
def index(self, req): # noqa
return self._index(req, key_type=True)
@wsgi.Controller.api_version("2.1", "2.1") # noqa return self._index(
@validation.query_schema(keypairs.index_query_schema_v20) req, key_type=key_type, user_id=user_id, links=links
@wsgi.expected_errors(()) )
def index(self, req): # noqa
return self._index(req)
def _index(self, req, key_type=False, user_id=None, links=False): def _index(self, req, key_type=False, user_id=None, links=False):
"""List of keypairs for a user.""" """List of keypairs for a user."""
@@ -245,7 +198,7 @@ class KeypairController(wsgi.Controller):
context.can(kp_policies.POLICY_ROOT % 'index', context.can(kp_policies.POLICY_ROOT % 'index',
target={'user_id': user_id}) target={'user_id': user_id})
if api_version_request.is_supported(req, min_version='2.35'): if api_version_request.is_supported(req, '2.35'):
limit, marker = common.get_limit_and_marker(req) limit, marker = common.get_limit_and_marker(req)
else: else:
limit = marker = None limit = marker = None

View File

@@ -13,14 +13,7 @@
# 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.api.openstack.api_version_request \ from nova.api.openstack import api_version_request
import MAX_IMAGE_META_PROXY_API_VERSION
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.api_version_request \
import MIN_WITHOUT_IMAGE_META_PROXY_API_VERSION
from nova.api.openstack.api_version_request \
import MIN_WITHOUT_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.compute.schemas import limits from nova.api.openstack.compute.schemas import limits
from nova.api.openstack.compute.views import limits as limits_views from nova.api.openstack.compute.views import limits as limits_views
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
@@ -44,32 +37,23 @@ FILTERED_LIMITS_2_57.extend(['injected_files', 'injected_file_content_bytes'])
class LimitsController(wsgi.Controller): class LimitsController(wsgi.Controller):
"""Controller for accessing limits in the OpenStack API.""" """Controller for accessing limits in the OpenStack API."""
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(()) @wsgi.expected_errors(())
@validation.query_schema(limits.limits_query_schema) @validation.query_schema(limits.limits_query_schema, '2.1', '2.56')
def index(self, req):
return self._index(req)
@wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, # noqa
MAX_IMAGE_META_PROXY_API_VERSION)
@wsgi.expected_errors(())
@validation.query_schema(limits.limits_query_schema)
def index(self, req): # noqa
return self._index(req, FILTERED_LIMITS_2_36)
@wsgi.Controller.api_version( # noqa
MIN_WITHOUT_IMAGE_META_PROXY_API_VERSION, '2.56')
@wsgi.expected_errors(())
@validation.query_schema(limits.limits_query_schema)
def index(self, req): # noqa
return self._index(req, FILTERED_LIMITS_2_36, max_image_meta=False)
@wsgi.Controller.api_version('2.57') # noqa
@wsgi.expected_errors(())
@validation.query_schema(limits.limits_query_schema_275, '2.75')
@validation.query_schema(limits.limits_query_schema, '2.57', '2.74') @validation.query_schema(limits.limits_query_schema, '2.57', '2.74')
def index(self, req): # noqa @validation.query_schema(limits.limits_query_schema_275, '2.75')
return self._index(req, FILTERED_LIMITS_2_57, max_image_meta=False) def index(self, req):
filtered_limits = []
if api_version_request.is_supported(req, '2.57'):
filtered_limits = FILTERED_LIMITS_2_57
elif api_version_request.is_supported(req, '2.36'):
filtered_limits = FILTERED_LIMITS_2_36
max_image_meta = True
if api_version_request.is_supported(req, '2.39'):
max_image_meta = False
return self._index(req, filtered_limits=filtered_limits,
max_image_meta=max_image_meta)
def _index(self, req, filtered_limits=None, max_image_meta=True): def _index(self, req, filtered_limits=None, max_image_meta=True):
"""Return all global limit information.""" """Return all global limit information."""
@@ -80,8 +64,7 @@ class LimitsController(wsgi.Controller):
project_id = req.GET.get('tenant_id') project_id = req.GET.get('tenant_id')
context.can(limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME) context.can(limits_policies.OTHER_PROJECT_LIMIT_POLICY_NAME)
quotas = QUOTAS.get_project_quotas(context, project_id, quotas = QUOTAS.get_project_quotas(context, project_id, usages=True)
usages=True)
builder = limits_views.ViewBuilder() builder = limits_views.ViewBuilder()
return builder.build(req, quotas, filtered_limits=filtered_limits, return builder.build(req, quotas, filtered_limits=filtered_limits,
max_image_meta=max_image_meta) max_image_meta=max_image_meta)

View File

@@ -15,7 +15,7 @@ from webob import exc
from nova.api.openstack import api_version_request from nova.api.openstack import api_version_request
from nova.api.openstack import common from nova.api.openstack import common
from nova.api.openstack.compute.schemas import migrations as schema_migrations from nova.api.openstack.compute.schemas import migrations as schema
from nova.api.openstack.compute.views import migrations as migrations_view from nova.api.openstack.compute.views import migrations as migrations_view
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.api import validation from nova.api import validation
@@ -145,47 +145,41 @@ class MigrationsController(wsgi.Controller):
migrations_dict['migrations_links'] = migrations_links migrations_dict['migrations_links'] = migrations_links
return migrations_dict return migrations_dict
@wsgi.Controller.api_version("2.1", "2.22") # noqa @wsgi.expected_errors((), "2.1", "2.58")
@wsgi.expected_errors(()) @wsgi.expected_errors(400, "2.59")
@validation.query_schema(schema_migrations.list_query_schema_v20, @validation.query_schema(schema.list_query_schema_v20, "2.0", "2.22")
"2.0", "2.22") @validation.query_schema(schema.list_query_schema_v20, "2.23", "2.58")
@validation.query_schema(schema.list_query_params_v259, "2.59", "2.65")
@validation.query_schema(schema.list_query_params_v266, "2.66", "2.79")
@validation.query_schema(schema.list_query_params_v280, "2.80")
def index(self, req): def index(self, req):
"""Return all migrations using the query parameters as filters.""" """Return all migrations using the query parameters as filters."""
return self._index(req) add_link = False
if api_version_request.is_supported(req, '2.23'):
add_link = True
@wsgi.Controller.api_version("2.23", "2.58") # noqa next_link = False
@wsgi.expected_errors(()) add_uuid = False
@validation.query_schema(schema_migrations.list_query_schema_v20, sort_keys = None
"2.23", "2.58") sort_dirs = None
def index(self, req): # noqa limit = None
"""Return all migrations using the query parameters as filters.""" marker = None
return self._index(req, add_link=True) allow_changes_since = False
if api_version_request.is_supported(req, '2.59'):
next_link = True
add_uuid = True
sort_keys = ['created_at', 'id']
# FIXME(stephenfin): This looks like a typo?
sort_dirs = ['desc', 'desc']
limit, marker = common.get_limit_and_marker(req)
allow_changes_since = True
@wsgi.Controller.api_version("2.59", "2.65") # noqa allow_changes_before = False
@wsgi.expected_errors(400) if api_version_request.is_supported(req, '2.66'):
@validation.query_schema(schema_migrations.list_query_params_v259, allow_changes_before = True
"2.59", "2.65")
def index(self, req): # noqa
"""Return all migrations using the query parameters as filters."""
limit, marker = common.get_limit_and_marker(req)
return self._index(req, add_link=True, next_link=True, add_uuid=True,
sort_keys=['created_at', 'id'],
sort_dirs=['desc', 'desc'],
limit=limit, marker=marker,
allow_changes_since=True)
@wsgi.Controller.api_version("2.66") # noqa return self._index(
@wsgi.expected_errors(400) req, add_link=add_link, next_link=next_link, add_uuid=add_uuid,
@validation.query_schema(schema_migrations.list_query_params_v266, sort_keys=sort_keys, sort_dirs=sort_dirs, limit=limit,
"2.66", "2.79") marker=marker, allow_changes_since=allow_changes_since,
@validation.query_schema(schema_migrations.list_query_params_v280, allow_changes_before=allow_changes_before)
"2.80")
def index(self, req): # noqa
"""Return all migrations using the query parameters as filters."""
limit, marker = common.get_limit_and_marker(req)
return self._index(req, add_link=True, next_link=True, add_uuid=True,
sort_keys=['created_at', 'id'],
sort_dirs=['desc', 'desc'],
limit=limit, marker=marker,
allow_changes_since=True,
allow_changes_before=True)

View File

@@ -16,6 +16,7 @@
import copy import copy
import webob import webob
from nova.api.openstack import api_version_request
from nova.api.openstack.compute.schemas import quota_classes from nova.api.openstack.compute.schemas import quota_classes
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.api import validation from nova.api import validation
@@ -76,23 +77,27 @@ class QuotaClassSetsController(wsgi.Controller):
return dict(quota_class_set=result) return dict(quota_class_set=result)
@wsgi.Controller.api_version('2.1', '2.49') def _get_filtered_quotas(self, req):
if api_version_request.is_supported(req, '2.57'):
return FILTERED_QUOTAS_2_57
elif api_version_request.is_supported(req, '2.50'):
return FILTERED_QUOTAS_2_50
else:
return []
@wsgi.expected_errors(()) @wsgi.expected_errors(())
@validation.query_schema(quota_classes.show_query) @validation.query_schema(quota_classes.show_query)
def show(self, req, id): def show(self, req, id):
return self._show(req, id, exclude_server_groups=True) filtered_quotas = self._get_filtered_quotas(req)
@wsgi.Controller.api_version('2.50', '2.56') # noqa exclude_server_groups = True
@wsgi.expected_errors(()) if api_version_request.is_supported(req, '2.50'):
@validation.query_schema(quota_classes.show_query) exclude_server_groups = False
def show(self, req, id): # noqa
return self._show(req, id, FILTERED_QUOTAS_2_50)
@wsgi.Controller.api_version('2.57') # noqa return self._show(
@wsgi.expected_errors(()) req, id, filtered_quotas=filtered_quotas,
@validation.query_schema(quota_classes.show_query) exclude_server_groups=exclude_server_groups,
def show(self, req, id): # noqa )
return self._show(req, id, FILTERED_QUOTAS_2_57)
def _show(self, req, id, filtered_quotas=None, def _show(self, req, id, filtered_quotas=None,
exclude_server_groups=False): exclude_server_groups=False):
@@ -102,23 +107,21 @@ class QuotaClassSetsController(wsgi.Controller):
return self._format_quota_set(id, values, filtered_quotas, return self._format_quota_set(id, values, filtered_quotas,
exclude_server_groups) exclude_server_groups)
@wsgi.Controller.api_version("2.1", "2.49") # noqa
@wsgi.expected_errors(400) @wsgi.expected_errors(400)
@validation.schema(quota_classes.update) @validation.schema(quota_classes.update, '2.1', '2.49')
@validation.schema(quota_classes.update_v250, '2.50', '2.56')
@validation.schema(quota_classes.update_v257, '2.57')
def update(self, req, id, body): def update(self, req, id, body):
return self._update(req, id, body, exclude_server_groups=True) filtered_quotas = self._get_filtered_quotas(req)
@wsgi.Controller.api_version("2.50", "2.56") # noqa exclude_server_groups = True
@wsgi.expected_errors(400) if api_version_request.is_supported(req, '2.50'):
@validation.schema(quota_classes.update_v250) exclude_server_groups = False
def update(self, req, id, body): # noqa
return self._update(req, id, body, FILTERED_QUOTAS_2_50)
@wsgi.Controller.api_version("2.57") # noqa return self._update(
@wsgi.expected_errors(400) req, id, body, filtered_quotas=filtered_quotas,
@validation.schema(quota_classes.update_v257) exclude_server_groups=exclude_server_groups,
def update(self, req, id, body): # noqa )
return self._update(req, id, body, FILTERED_QUOTAS_2_57)
def _update(self, req, id, body, filtered_quotas=None, def _update(self, req, id, body, filtered_quotas=None,
exclude_server_groups=False): exclude_server_groups=False):

View File

@@ -18,10 +18,7 @@ from urllib import parse as urlparse
from oslo_utils import strutils from oslo_utils import strutils
import webob import webob
from nova.api.openstack.api_version_request \ from nova.api.openstack import api_version_request
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.api_version_request \
import MIN_WITHOUT_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.compute.schemas import quota_sets from nova.api.openstack.compute.schemas import quota_sets
from nova.api.openstack import identity from nova.api.openstack import identity
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
@@ -105,24 +102,21 @@ class QuotaSetsController(wsgi.Controller):
else: else:
return {k: v['limit'] for k, v in values.items()} return {k: v['limit'] for k, v in values.items()}
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) def _get_filtered_quotas(self, req):
@wsgi.expected_errors(400) if api_version_request.is_supported(req, '2.57'):
@validation.query_schema(quota_sets.show_query, '2.0', '2.74') return FILTERED_QUOTAS_2_57
def show(self, req, id): elif api_version_request.is_supported(req, '2.36'):
return self._show(req, id, []) return FILTERED_QUOTAS_2_36
else:
return []
@wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56') @wsgi.Controller.api_version('2.1')
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
def show(self, req, id): # noqa
return self._show(req, id, FILTERED_QUOTAS_2_36)
@wsgi.Controller.api_version('2.57') # noqa
@wsgi.expected_errors(400) @wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74') @validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75') @validation.query_schema(quota_sets.show_query_v275, '2.75')
def show(self, req, id): # noqa def show(self, req, id):
return self._show(req, id, FILTERED_QUOTAS_2_57) filtered_quotas = self._get_filtered_quotas(req)
return self._show(req, id, filtered_quotas)
def _show(self, req, id, filtered_quotas): def _show(self, req, id, filtered_quotas):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -131,29 +125,17 @@ class QuotaSetsController(wsgi.Controller):
params = urlparse.parse_qs(req.environ.get('QUERY_STRING', '')) params = urlparse.parse_qs(req.environ.get('QUERY_STRING', ''))
user_id = params.get('user_id', [None])[0] user_id = params.get('user_id', [None])[0]
return self._format_quota_set(id, return self._format_quota_set(
id,
self._get_quotas(context, id, user_id=user_id), self._get_quotas(context, id, user_id=user_id),
filtered_quotas=filtered_quotas) filtered_quotas=filtered_quotas)
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400) @wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74') @validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75')
def detail(self, req, id): def detail(self, req, id):
return self._detail(req, id, []) filtered_quotas = self._get_filtered_quotas(req)
return self._detail(req, id, filtered_quotas)
@wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75')
def detail(self, req, id): # noqa
return self._detail(req, id, FILTERED_QUOTAS_2_36)
@wsgi.Controller.api_version('2.57') # noqa
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75')
def detail(self, req, id): # noqa
return self._detail(req, id, FILTERED_QUOTAS_2_57)
def _detail(self, req, id, filtered_quotas): def _detail(self, req, id, filtered_quotas):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -166,26 +148,16 @@ class QuotaSetsController(wsgi.Controller):
self._get_quotas(context, id, user_id=user_id, usages=True), self._get_quotas(context, id, user_id=user_id, usages=True),
filtered_quotas=filtered_quotas) filtered_quotas=filtered_quotas)
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.Controller.api_version('2.1')
@wsgi.expected_errors(400) @wsgi.expected_errors(400)
@validation.schema(quota_sets.update) @validation.schema(quota_sets.update, '2.0', '2.35')
def update(self, req, id, body): @validation.schema(quota_sets.update_v236, '2.36', '2.56')
return self._update(req, id, body, []) @validation.schema(quota_sets.update_v257, '2.57')
@wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@wsgi.expected_errors(400)
@validation.schema(quota_sets.update_v236)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
def update(self, req, id, body): # noqa
return self._update(req, id, body, FILTERED_QUOTAS_2_36)
@wsgi.Controller.api_version('2.57') # noqa
@wsgi.expected_errors(400)
@validation.schema(quota_sets.update_v257)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74') @validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75') @validation.query_schema(quota_sets.show_query_v275, '2.75')
def update(self, req, id, body): # noqa def update(self, req, id, body):
return self._update(req, id, body, FILTERED_QUOTAS_2_57) filtered_quotas = self._get_filtered_quotas(req)
return self._update(req, id, body, filtered_quotas)
def _update(self, req, id, body, filtered_quotas): def _update(self, req, id, body, filtered_quotas):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -249,23 +221,12 @@ class QuotaSetsController(wsgi.Controller):
self._get_quotas(context, id, user_id=user_id), self._get_quotas(context, id, user_id=user_id),
filtered_quotas=filtered_quotas) filtered_quotas=filtered_quotas)
@wsgi.Controller.api_version("2.0", MAX_PROXY_API_SUPPORT_VERSION) @wsgi.Controller.api_version('2.0')
@wsgi.expected_errors(400) @wsgi.expected_errors(400)
@validation.query_schema(quota_sets.defaults_query) @validation.query_schema(quota_sets.defaults_query)
def defaults(self, req, id): def defaults(self, req, id):
return self._defaults(req, id, []) filtered_quotas = self._get_filtered_quotas(req)
return self._defaults(req, id, filtered_quotas)
@wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.defaults_query)
def defaults(self, req, id): # noqa
return self._defaults(req, id, FILTERED_QUOTAS_2_36)
@wsgi.Controller.api_version('2.57') # noqa
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.defaults_query)
def defaults(self, req, id): # noqa
return self._defaults(req, id, FILTERED_QUOTAS_2_57)
def _defaults(self, req, id, filtered_quotas): def _defaults(self, req, id, filtered_quotas):
context = req.environ['nova.context'] context = req.environ['nova.context']

View File

@@ -53,7 +53,7 @@ service_update_v211 = {
# be specified in the body. If status=='disabled', then 'disabled_reason' is # be specified in the body. If status=='disabled', then 'disabled_reason' is
# also checked in the body but is not required. Requesting status='enabled' and # also checked in the body but is not required. Requesting status='enabled' and
# including a 'disabled_reason' results in a 400, but this is checked in code. # including a 'disabled_reason' results in a 400, but this is checked in code.
service_update_v2_53 = { service_update_v253 = {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'status': { 'status': {

View File

@@ -51,8 +51,8 @@ show_query_v240 = copy.deepcopy(show_query)
show_query_v240['properties'].update( show_query_v240['properties'].update(
parameter_types.pagination_parameters) parameter_types.pagination_parameters)
index_query_275 = copy.deepcopy(index_query_v240) index_query_v275 = copy.deepcopy(index_query_v240)
index_query_275['additionalProperties'] = False index_query_v275['additionalProperties'] = False
show_query_275 = copy.deepcopy(show_query_v240) show_query_v275 = copy.deepcopy(show_query_v240)
show_query_275['additionalProperties'] = False show_query_v275['additionalProperties'] = False

View File

@@ -369,9 +369,9 @@ class ServiceController(wsgi.Controller):
'in-progress migrations. Complete the ' 'in-progress migrations. Complete the '
'migrations or delete the instances first.')) 'migrations or delete the instances first.'))
@validation.query_schema(services.index_query_schema_275, '2.75')
@validation.query_schema(services.index_query_schema, '2.0', '2.74')
@wsgi.expected_errors(()) @wsgi.expected_errors(())
@validation.query_schema(services.index_query_schema, '2.0', '2.74')
@validation.query_schema(services.index_query_schema_275, '2.75')
def index(self, req): def index(self, req):
"""Return a list of all running services. Filter by host & service """Return a list of all running services. Filter by host & service
name name
@@ -385,10 +385,10 @@ class ServiceController(wsgi.Controller):
return {'services': _services} return {'services': _services}
@wsgi.Controller.api_version('2.1', '2.52')
@wsgi.expected_errors((400, 404)) @wsgi.expected_errors((400, 404))
@validation.schema(services.service_update, '2.0', '2.10') @validation.schema(services.service_update, '2.0', '2.10')
@validation.schema(services.service_update_v211, '2.11', '2.52') @validation.schema(services.service_update_v211, '2.11', '2.52')
@validation.schema(services.service_update_v253, '2.53')
def update(self, req, id, body): def update(self, req, id, body):
"""Perform service update """Perform service update
@@ -396,7 +396,17 @@ class ServiceController(wsgi.Controller):
to identify the service on which to perform the action. There is no to identify the service on which to perform the action. There is no
service ID passed on the path, just the action, for example service ID passed on the path, just the action, for example
PUT /os-services/disable. PUT /os-services/disable.
Starting with microversion 2.53, the service uuid is passed in on the
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'):
return self._update_v253(req, id, body)
else:
return self._update_v21(req, id, body)
def _update_v21(self, req, id, body):
context = req.environ['nova.context'] context = req.environ['nova.context']
context.can(services_policies.BASE_POLICY_NAME % 'update', target={}) 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, min_version='2.11'):
@@ -407,16 +417,7 @@ class ServiceController(wsgi.Controller):
return self._perform_action(req, id, body, actions) return self._perform_action(req, id, body, actions)
@wsgi.Controller.api_version('2.53') # noqa F811 def _update_v253(self, req, id, body):
@wsgi.expected_errors((400, 404))
@validation.schema(services.service_update_v2_53, '2.53')
def update(self, req, id, body): # noqa
"""Perform service update
Starting with microversion 2.53, the service uuid is passed in on the
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.
"""
service_id = id service_id = id
# Validate that the service ID is a UUID. # Validate that the service ID is a UUID.
if not uuidutils.is_uuid_like(service_id): if not uuidutils.is_uuid_like(service_id):

View File

@@ -21,6 +21,7 @@ import iso8601
from oslo_utils import timeutils from oslo_utils import timeutils
from webob import exc from webob import exc
from nova.api.openstack import api_version_request
from nova.api.openstack import common from nova.api.openstack import common
from nova.api.openstack.compute.schemas import simple_tenant_usage as schema from nova.api.openstack.compute.schemas import simple_tenant_usage as schema
from nova.api.openstack.compute.views import usages as usages_view from nova.api.openstack.compute.views import usages as usages_view
@@ -178,7 +179,7 @@ class SimpleTenantUsageController(wsgi.Controller):
info['ended_at'] = ( info['ended_at'] = (
timeutils.normalize_time(instance.terminated_at) if timeutils.normalize_time(instance.terminated_at) if
instance.terminated_at else None) instance.terminated_at else None)
if info['ended_at']: if info['ended_at']:
info['state'] = 'terminated' info['state'] = 'terminated'
@@ -261,35 +262,17 @@ class SimpleTenantUsageController(wsgi.Controller):
detailed = env.get('detailed', ['0'])[0] == '1' detailed = env.get('detailed', ['0'])[0] == '1'
return (period_start, period_stop, detailed) return (period_start, period_stop, detailed)
@wsgi.Controller.api_version("2.40") @validation.query_schema(schema.index_query, '2.1', '2.39')
@validation.query_schema(schema.index_query_275, '2.75')
@validation.query_schema(schema.index_query_v240, '2.40', '2.74') @validation.query_schema(schema.index_query_v240, '2.40', '2.74')
@validation.query_schema(schema.index_query_v275, '2.75')
@wsgi.expected_errors(400) @wsgi.expected_errors(400)
def index(self, req): def index(self, req):
"""Retrieve tenant_usage for all tenants.""" """Retrieve tenant_usage for all tenants."""
return self._index(req, links=True) links = False
if api_version_request.is_supported(req, '2.40'):
links = True
@wsgi.Controller.api_version("2.1", "2.39") # noqa return self._index(req, links=links)
@validation.query_schema(schema.index_query)
@wsgi.expected_errors(400)
def index(self, req): # noqa
"""Retrieve tenant_usage for all tenants."""
return self._index(req)
@wsgi.Controller.api_version("2.40")
@validation.query_schema(schema.show_query_275, '2.75')
@validation.query_schema(schema.show_query_v240, '2.40', '2.74')
@wsgi.expected_errors(400)
def show(self, req, id):
"""Retrieve tenant_usage for a specified tenant."""
return self._show(req, id, links=True)
@wsgi.Controller.api_version("2.1", "2.39") # noqa
@validation.query_schema(schema.show_query)
@wsgi.expected_errors(400)
def show(self, req, id): # noqa
"""Retrieve tenant_usage for a specified tenant."""
return self._show(req, id)
def _index(self, req, links=False): def _index(self, req, links=False):
context = req.environ['nova.context'] context = req.environ['nova.context']
@@ -327,6 +310,18 @@ class SimpleTenantUsageController(wsgi.Controller):
return tenant_usages return tenant_usages
@validation.query_schema(schema.show_query, '2.1', '2.39')
@validation.query_schema(schema.show_query_v240, '2.40', '2.74')
@validation.query_schema(schema.show_query_v275, '2.75')
@wsgi.expected_errors(400)
def show(self, req, id):
"""Retrieve tenant_usage for a specified tenant."""
links = False
if api_version_request.is_supported(req, '2.40'):
links = True
return self._show(req, id, links=links)
def _show(self, req, id, links=False): def _show(self, req, id, links=False):
tenant_id = id tenant_id = id
context = req.environ['nova.context'] context = req.environ['nova.context']