Merge "api: Add remaining missing query parameter schema"

This commit is contained in:
Zuul 2024-07-20 08:50:32 +00:00 committed by Gerrit Code Review
commit 92442bfaf1
93 changed files with 769 additions and 74 deletions

View File

@ -33,6 +33,7 @@ class AgentController(wsgi.Controller):
"""
@wsgi.expected_errors(410)
@wsgi.removed('22.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
raise exc.HTTPGone()

View File

@ -49,6 +49,7 @@ class AggregateController(wsgi.Controller):
self.conductor_tasks = conductor.ComputeTaskAPI()
@wsgi.expected_errors(())
@validation.query_schema(aggregates.index_query)
def index(self, req):
"""Returns a list a host aggregate's id, name, availability_zone."""
context = _get_context(req)
@ -94,6 +95,7 @@ class AggregateController(wsgi.Controller):
return agg
@wsgi.expected_errors((400, 404))
@validation.query_schema(aggregates.show_query)
def show(self, req, id):
"""Shows the details of an aggregate, hosts and metadata included."""
context = _get_context(req)

View File

@ -64,6 +64,7 @@ class InterfaceAttachmentController(wsgi.Controller):
self.network_api = neutron.API()
@wsgi.expected_errors((404, 501))
@validation.query_schema(attach_interfaces.index_query)
def index(self, req, server_id):
"""Returns the list of interface attachments for a given instance."""
context = req.environ['nova.context']
@ -106,6 +107,7 @@ class InterfaceAttachmentController(wsgi.Controller):
return {'interfaceAttachments': results}
@wsgi.expected_errors((403, 404))
@validation.query_schema(attach_interfaces.show_query)
def show(self, req, server_id, id):
"""Return data about the given interface attachment."""
context = req.environ['nova.context']

View File

@ -12,7 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from nova.api.openstack.compute.schemas import availability_zone as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova import availability_zones
from nova.compute import api as compute
import nova.conf
@ -103,6 +105,7 @@ class AvailabilityZoneController(wsgi.Controller):
return {'availabilityZoneInfo': result}
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
"""Returns a summary list of availability zone."""
context = req.environ['nova.context']
@ -111,6 +114,7 @@ class AvailabilityZoneController(wsgi.Controller):
return self._describe_availability_zones(context)
@wsgi.expected_errors(())
@validation.query_schema(schema.detail_query)
def detail(self, req):
"""Returns a detailed list of availability zone."""
context = req.environ['nova.context']

View File

@ -21,8 +21,7 @@ import webob
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.compute.schemas \
import baremetal_nodes as schema_baremetal_nodes
from nova.api.openstack.compute.schemas import baremetal_nodes as schema
from nova.api.openstack import wsgi
from nova.api import validation
import nova.conf
@ -63,6 +62,7 @@ class BareMetalNodeController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((404, 501))
@validation.query_schema(schema.index_query)
def index(self, req):
context = req.environ['nova.context']
context.can(bn_policies.BASE_POLICY_NAME % 'list', target={})
@ -86,6 +86,7 @@ class BareMetalNodeController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((404, 501))
@validation.query_schema(schema.show_query)
def show(self, req, id):
context = req.environ['nova.context']
context.can(bn_policies.BASE_POLICY_NAME % 'show', target={})
@ -115,7 +116,7 @@ class BareMetalNodeController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400)
@validation.schema(schema_baremetal_nodes.create)
@validation.schema(schema.create)
def create(self, req, body):
_no_ironic_proxy("node-create")
@ -127,13 +128,13 @@ class BareMetalNodeController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.action('add_interface')
@wsgi.expected_errors(400)
@validation.schema(schema_baremetal_nodes.add_interface)
@validation.schema(schema.add_interface)
def _add_interface(self, req, id, body):
_no_ironic_proxy("port-create")
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.action('remove_interface')
@wsgi.expected_errors(400)
@validation.schema(schema_baremetal_nodes.remove_interface)
@validation.schema(schema.remove_interface)
def _remove_interface(self, req, id, body):
_no_ironic_proxy("port-delete")

View File

@ -36,26 +36,31 @@ class CellsController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('20.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
raise exc.HTTPGone()
@wsgi.expected_errors(410)
@wsgi.removed('20.0.0', _removal_reason)
@validation.query_schema(schema.detail_query)
def detail(self, req):
raise exc.HTTPGone()
@wsgi.expected_errors(410)
@wsgi.removed('20.0.0', _removal_reason)
@validation.query_schema(schema.info_query)
def info(self, req):
raise exc.HTTPGone()
@wsgi.expected_errors(410)
@wsgi.removed('20.0.0', _removal_reason)
@validation.query_schema(schema.capacities_query)
def capacities(self, req, id=None):
raise exc.HTTPGone()
@wsgi.expected_errors(410)
@wsgi.removed('20.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, id):
raise exc.HTTPGone()

View File

@ -31,6 +31,7 @@ class CertificatesController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('16.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, id):
"""Return certificate information."""
raise webob.exc.HTTPGone()

View File

@ -39,6 +39,7 @@ class CloudpipeController(wsgi.Controller):
@wsgi.expected_errors((410))
@wsgi.removed('16.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
"""List running cloudpipe instances."""
raise exc.HTTPGone()

View File

@ -15,7 +15,9 @@
import webob
from nova.api.openstack.compute.schemas import console_auth_tokens as schema
from nova.api.openstack import wsgi
from nova.api import validation
import nova.conf
from nova import context as nova_context
from nova.i18n import _
@ -64,6 +66,7 @@ class ConsoleAuthTokensController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.30")
@wsgi.expected_errors((400, 401, 404))
@validation.query_schema(schema.show_query)
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
@ -77,5 +80,6 @@ class ConsoleAuthTokensController(wsgi.Controller):
@wsgi.Controller.api_version("2.31") # noqa
@wsgi.expected_errors((400, 404))
@validation.query_schema(schema.show_query)
def show(self, req, id): # noqa
return self._show(req, id)

View File

@ -35,6 +35,7 @@ class ConsolesController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('21.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req, server_id):
raise exc.HTTPGone()
@ -46,6 +47,7 @@ class ConsolesController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('21.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, server_id, id):
raise exc.HTTPGone()

View File

@ -14,7 +14,9 @@
import webob.exc
from nova.api.openstack.compute.schemas import extension_info as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova.policies import extensions as ext_policies
@ -127,7 +129,7 @@ EXTENSION_LIST = [
"alias": "os-admin-actions",
"description": "Enable admin-only server actions\n\n "
"Actions include: resetNetwork, injectNetworkInfo, "
"os-resetState\n ",
"os-resetState\n ",
"links": [],
"name": "AdminActions",
"namespace": "http://docs.openstack.org/compute/ext/fake_xml",
@ -853,6 +855,7 @@ EXTENSION_LIST_LEGACY_V2_COMPATIBLE = sorted(
class ExtensionInfoController(wsgi.Controller):
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
context = req.environ['nova.context']
context.can(ext_policies.BASE_POLICY_NAME, target={})
@ -865,6 +868,7 @@ class ExtensionInfoController(wsgi.Controller):
return dict(extensions=EXTENSION_LIST)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id):
context = req.environ['nova.context']
context.can(ext_policies.BASE_POLICY_NAME, target={})

View File

@ -30,6 +30,7 @@ class FixedIPController(wsgi.Controller):
@wsgi.expected_errors((410))
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema_fixed_ips.show_query)
def show(self, req, id):
raise exc.HTTPGone()

View File

@ -19,7 +19,7 @@ import webob
from nova.api.openstack import api_version_request
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import flavor_access
from nova.api.openstack.compute.schemas import flavor_access as schema
from nova.api.openstack import identity
from nova.api.openstack import wsgi
from nova.api import validation
@ -39,7 +39,9 @@ def _marshall_flavor_access(flavor):
class FlavorAccessController(wsgi.Controller):
"""The flavor access API controller for the OpenStack API."""
@wsgi.expected_errors(404)
@validation.query_schema(schema.index_query)
def index(self, req, flavor_id):
context = req.environ['nova.context']
context.can(fa_policies.BASE_POLICY_NAME)
@ -60,7 +62,7 @@ class FlavorActionController(wsgi.Controller):
@wsgi.expected_errors((400, 403, 404, 409))
@wsgi.action("addTenantAccess")
@validation.schema(flavor_access.add_tenant_access)
@validation.schema(schema.add_tenant_access)
def _add_tenant_access(self, req, id, body):
context = req.environ['nova.context']
context.can(fa_policies.POLICY_ROOT % "add_tenant_access", target={})
@ -85,7 +87,7 @@ class FlavorActionController(wsgi.Controller):
@wsgi.expected_errors((400, 403, 404))
@wsgi.action("removeTenantAccess")
@validation.schema(flavor_access.remove_tenant_access)
@validation.schema(schema.remove_tenant_access)
def _remove_tenant_access(self, req, id, body):
context = req.environ['nova.context']
context.can(

View File

@ -155,6 +155,7 @@ class FlavorsController(wsgi.Controller):
req, limited_flavors, include_extra_specs=include_extra_specs)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id):
"""Return data about the given flavor id."""
context = req.environ['nova.context']

View File

@ -17,7 +17,7 @@ import webob
from nova.api.openstack import api_version_request
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import flavors_extraspecs
from nova.api.openstack.compute.schemas import flavors_extraspecs as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova.api.validation.extra_specs import validators
@ -56,6 +56,7 @@ class FlavorExtraSpecsController(wsgi.Controller):
validators.validate(name, value)
@wsgi.expected_errors(404)
@validation.query_schema(schema.index_query)
def index(self, req, flavor_id):
"""Returns the list of extra specs for a given flavor."""
context = req.environ['nova.context']
@ -67,7 +68,7 @@ class FlavorExtraSpecsController(wsgi.Controller):
# +microversions because the flavor extra specs has been created
# completely when returning a response.
@wsgi.expected_errors((400, 404, 409))
@validation.schema(flavors_extraspecs.create)
@validation.schema(schema.create)
def create(self, req, flavor_id, body):
context = req.environ['nova.context']
context.can(fes_policies.POLICY_ROOT % 'create', target={})
@ -85,7 +86,7 @@ class FlavorExtraSpecsController(wsgi.Controller):
return body
@wsgi.expected_errors((400, 404, 409))
@validation.schema(flavors_extraspecs.update)
@validation.schema(schema.update)
def update(self, req, flavor_id, id, body):
context = req.environ['nova.context']
context.can(fes_policies.POLICY_ROOT % 'update', target={})
@ -105,6 +106,7 @@ class FlavorExtraSpecsController(wsgi.Controller):
return body
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, flavor_id, id):
"""Return a single extra spec item."""
context = req.environ['nova.context']

View File

@ -31,6 +31,7 @@ class FloatingIPDNSDomainController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
raise exc.HTTPGone()
@ -51,6 +52,7 @@ class FloatingIPDNSEntryController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, domain_id, id):
raise exc.HTTPGone()

View File

@ -14,7 +14,9 @@
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack.compute.schemas import floating_ip_pools as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova.network import neutron
from nova.policies import floating_ip_pools as fip_policies
@ -41,6 +43,7 @@ class FloatingIPPoolsController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
"""Return a list of pools."""
context = req.environ['nova.context']

View File

@ -22,7 +22,7 @@ import webob
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import floating_ips
from nova.api.openstack.compute.schemas import floating_ips as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova.compute import api as compute
@ -84,6 +84,7 @@ class FloatingIPController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((400, 404))
@validation.query_schema(schema.show_query)
def show(self, req, id):
"""Return data about the given floating IP."""
context = req.environ['nova.context']
@ -102,6 +103,7 @@ class FloatingIPController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
"""Return a list of floating IPs allocated to a project."""
context = req.environ['nova.context']
@ -115,7 +117,7 @@ class FloatingIPController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((400, 403, 404))
@validation.schema(floating_ips.create)
@validation.schema(schema.create)
def create(self, req, body=None):
context = req.environ['nova.context']
context.can(fi_policies.BASE_POLICY_NAME % 'create',
@ -187,7 +189,7 @@ class FloatingIPActionController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.43")
@wsgi.expected_errors((400, 403, 404))
@wsgi.action('addFloatingIp')
@validation.schema(floating_ips.add_floating_ip)
@validation.schema(schema.add_floating_ip)
def _add_floating_ip(self, req, id, body):
"""Associate floating_ip to an instance."""
context = req.environ['nova.context']
@ -267,7 +269,7 @@ class FloatingIPActionController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.43")
@wsgi.expected_errors((400, 403, 404, 409))
@wsgi.action('removeFloatingIp')
@validation.schema(floating_ips.remove_floating_ip)
@validation.schema(schema.remove_floating_ip)
def _remove_floating_ip(self, req, id, body):
"""Dissociate floating_ip from an instance."""
context = req.environ['nova.context']

View File

@ -30,11 +30,13 @@ class FloatingIPBulkController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
raise exc.HTTPGone()
@wsgi.expected_errors(410)
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, id):
raise exc.HTTPGone()

View File

@ -16,7 +16,9 @@
from webob import exc
from nova.api.openstack.compute.schemas import fping as schema
from nova.api.openstack import wsgi
from nova.api import validation
_removal_reason = """\
This API only works with *nova-network*, which was deprecated in the
@ -30,10 +32,12 @@ class FpingController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
raise exc.HTTPGone()
@wsgi.expected_errors(410)
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, id):
raise exc.HTTPGone()

View File

@ -182,6 +182,7 @@ class HostController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.42")
@wsgi.expected_errors((400, 404, 501))
@validation.query_schema(hosts.startup_query)
def startup(self, req, id):
context = req.environ['nova.context']
context.can(hosts_policies.POLICY_NAME % 'start',
@ -190,6 +191,7 @@ class HostController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.42")
@wsgi.expected_errors((400, 404, 501))
@validation.query_schema(hosts.shutdown_query)
def shutdown(self, req, id):
context = req.environ['nova.context']
context.can(hosts_policies.POLICY_NAME % 'shutdown',
@ -198,6 +200,7 @@ class HostController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.42")
@wsgi.expected_errors((400, 404, 501))
@validation.query_schema(hosts.reboot_query)
def reboot(self, req, id):
context = req.environ['nova.context']
context.can(hosts_policies.POLICY_NAME % 'reboot',
@ -255,6 +258,7 @@ class HostController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.42")
@wsgi.expected_errors(404)
@validation.query_schema(hosts.show_query)
def show(self, req, id):
"""Shows the physical/usage resource given by hosts.

View File

@ -227,9 +227,9 @@ class HypervisorsController(wsgi.Controller):
return hypervisors_dict
@wsgi.Controller.api_version(UUID_FOR_ID_MIN_VERSION)
@validation.query_schema(hyper_schema.list_query_schema_v253,
UUID_FOR_ID_MIN_VERSION)
@wsgi.expected_errors((400, 404))
@validation.query_schema(hyper_schema.index_query_v253,
UUID_FOR_ID_MIN_VERSION)
def index(self, req):
"""Starting with the 2.53 microversion, the id field in the response
is the compute_nodes.uuid value. Also, the search and servers routes
@ -241,14 +241,15 @@ class HypervisorsController(wsgi.Controller):
return self._index(req, limit=limit, marker=marker, links=True)
@wsgi.Controller.api_version("2.33", "2.52") # noqa
@validation.query_schema(hyper_schema.list_query_schema_v233)
@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)
@ -259,9 +260,9 @@ class HypervisorsController(wsgi.Controller):
marker=marker, links=links)
@wsgi.Controller.api_version(UUID_FOR_ID_MIN_VERSION)
@validation.query_schema(hyper_schema.list_query_schema_v253,
UUID_FOR_ID_MIN_VERSION)
@wsgi.expected_errors((400, 404))
@validation.query_schema(hyper_schema.index_query_v253,
UUID_FOR_ID_MIN_VERSION)
def detail(self, req):
"""Starting with the 2.53 microversion, the id field in the response
is the compute_nodes.uuid value. Also, the search and servers routes
@ -273,14 +274,15 @@ class HypervisorsController(wsgi.Controller):
return self._detail(req, limit=limit, marker=marker, links=True)
@wsgi.Controller.api_version("2.33", "2.52") # noqa
@validation.query_schema(hyper_schema.list_query_schema_v233)
@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)
@ -317,9 +319,9 @@ class HypervisorsController(wsgi.Controller):
raise webob.exc.HTTPNotFound(explanation=msg)
@wsgi.Controller.api_version(UUID_FOR_ID_MIN_VERSION)
@validation.query_schema(hyper_schema.show_query_schema_v253,
UUID_FOR_ID_MIN_VERSION)
@wsgi.expected_errors((400, 404))
@validation.query_schema(hyper_schema.show_query_v253,
UUID_FOR_ID_MIN_VERSION)
def show(self, req, id):
"""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.
@ -333,6 +335,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.52") # noqa F811
@wsgi.expected_errors(404)
@validation.query_schema(hyper_schema.show_query)
def show(self, req, id): # noqa
return self._show(req, id)
@ -377,6 +380,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.87')
@wsgi.expected_errors((400, 404, 501))
@validation.query_schema(hyper_schema.uptime_query)
def uptime(self, req, id):
"""Prior to microversion 2.88, you could retrieve a special version of
the hypervisor detail view that included uptime. Starting in 2.88, this
@ -429,6 +433,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.52')
@wsgi.expected_errors(404)
@validation.query_schema(hyper_schema.search_query)
def search(self, req, id):
"""Prior to microversion 2.53 you could search for hypervisors by a
hostname pattern on a dedicated route. Starting with 2.53, searching
@ -467,6 +472,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.52')
@wsgi.expected_errors(404)
@validation.query_schema(hyper_schema.servers_query)
def servers(self, req, id):
"""Prior to microversion 2.53 you could search for hypervisors by a
hostname pattern and include servers on those hosts in the response on
@ -512,6 +518,7 @@ class HypervisorsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.87')
@wsgi.expected_errors(())
@validation.query_schema(hyper_schema.statistics_query)
def statistics(self, req):
"""Prior to microversion 2.88, you could get statistics for the
hypervisor. Most of these are now accessible from placement and the few

View File

@ -45,6 +45,7 @@ class ImageMetadataController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
@wsgi.expected_errors((403, 404))
@validation.query_schema(image_metadata.index_query)
def index(self, req, image_id):
"""Returns the list of metadata for a given instance."""
context = req.environ['nova.context']
@ -53,6 +54,7 @@ class ImageMetadataController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
@wsgi.expected_errors((403, 404))
@validation.query_schema(image_metadata.show_query)
def show(self, req, image_id, id):
context = req.environ['nova.context']
metadata = self._get_image(context, image_id)['properties']

View File

@ -18,8 +18,10 @@ import webob.exc
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import images as schema
from nova.api.openstack.compute.views import images as views_images
from nova.api.openstack import wsgi
from nova.api import validation
from nova import exception
from nova.i18n import _
from nova.image import glance
@ -74,6 +76,7 @@ class ImagesController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id):
"""Return detailed information about a specific image.
@ -113,6 +116,7 @@ class ImagesController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400)
@validation.query_schema(schema.index_query)
def index(self, req):
"""Return an index listing of images available to the request.
@ -132,6 +136,7 @@ class ImagesController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400)
@validation.query_schema(schema.detail_query)
def detail(self, req):
"""Return a detailed index listing of images available to the request.

View File

@ -83,6 +83,7 @@ class InstanceActionsController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", "2.57")
@wsgi.expected_errors(404)
@validation.query_schema(schema_instance_actions.list_query)
def index(self, req, server_id):
"""Returns the list of actions recorded for a given instance."""
context = req.environ["nova.context"]
@ -96,9 +97,9 @@ class InstanceActionsController(wsgi.Controller):
@wsgi.Controller.api_version("2.58") # noqa
@wsgi.expected_errors((400, 404))
@validation.query_schema(schema_instance_actions.list_query_params_v266,
@validation.query_schema(schema_instance_actions.list_query_v266,
"2.66")
@validation.query_schema(schema_instance_actions.list_query_params_v258,
@validation.query_schema(schema_instance_actions.list_query_v258,
"2.58", "2.65")
def index(self, req, server_id): # noqa
"""Returns the list of actions recorded for a given instance."""
@ -139,6 +140,7 @@ class InstanceActionsController(wsgi.Controller):
return actions_dict
@wsgi.expected_errors(404)
@validation.query_schema(schema_instance_actions.show_query)
def show(self, req, server_id, id):
"""Return data about the given instance action."""
context = req.environ['nova.context']

View File

@ -13,12 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import webob.exc
from nova.api.openstack.compute.schemas import instance_usage_audit_log as schema # noqa: E501
from nova.api.openstack import wsgi
from nova.api import validation
from nova.compute import api as compute
from nova.compute import rpcapi as compute_rpcapi
from nova.i18n import _
@ -33,6 +34,7 @@ class InstanceUsageAuditLogController(wsgi.Controller):
self.host_api = compute.HostAPI()
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
context = req.environ['nova.context']
context.can(iual_policies.BASE_POLICY_NAME % 'list', target={})
@ -40,6 +42,7 @@ class InstanceUsageAuditLogController(wsgi.Controller):
return {'instance_usage_audit_logs': task_log}
@wsgi.expected_errors(400)
@validation.query_schema(schema.show_query)
def show(self, req, id):
context = req.environ['nova.context']
context.can(iual_policies.BASE_POLICY_NAME % 'show', target={})

View File

@ -16,8 +16,10 @@
from webob import exc
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import addresses as schema
from nova.api.openstack.compute.views import addresses as views_addresses
from nova.api.openstack import wsgi
from nova.api import validation
from nova.compute import api as compute
from nova.i18n import _
from nova.policies import ips as ips_policies
@ -32,6 +34,7 @@ class IPsController(wsgi.Controller):
self._compute_api = compute.API()
@wsgi.expected_errors(404)
@validation.query_schema(schema.index_query)
def index(self, req, server_id):
context = req.environ["nova.context"]
instance = common.get_instance(self._compute_api, context, server_id)
@ -41,6 +44,7 @@ class IPsController(wsgi.Controller):
return self._view_builder.index(req, networks)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, server_id, id):
context = req.environ["nova.context"]
instance = common.get_instance(self._compute_api, context, server_id)

View File

@ -177,8 +177,8 @@ class KeypairController(wsgi.Controller):
return user_id
@wsgi.Controller.api_version("2.10")
@validation.query_schema(keypairs.show_query_schema_v275, '2.75')
@validation.query_schema(keypairs.show_query_schema_v210, '2.10', '2.74')
@validation.query_schema(keypairs.show_query_schema_v275, '2.75')
@wsgi.expected_errors(404)
def show(self, req, id):
# handle optional user-id for admin only

View File

@ -79,6 +79,7 @@ class NetworkController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
context = req.environ['nova.context']
context.can(net_policies.POLICY_ROOT % 'list',
@ -89,6 +90,7 @@ class NetworkController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id):
context = req.environ['nova.context']
context.can(net_policies.POLICY_ROOT % 'show',

View File

@ -78,16 +78,19 @@ class QuotaClassSetsController(wsgi.Controller):
@wsgi.Controller.api_version('2.1', '2.49')
@wsgi.expected_errors(())
@validation.query_schema(quota_classes.show_query)
def show(self, req, id):
return self._show(req, id, exclude_server_groups=True)
@wsgi.Controller.api_version('2.50', '2.56') # noqa
@wsgi.expected_errors(())
@validation.query_schema(quota_classes.show_query)
def show(self, req, id): # noqa
return self._show(req, id, FILTERED_QUOTAS_2_50)
@wsgi.Controller.api_version('2.57') # noqa
@wsgi.expected_errors(())
@validation.query_schema(quota_classes.show_query)
def show(self, req, id): # noqa
return self._show(req, id, FILTERED_QUOTAS_2_57)

View File

@ -107,22 +107,23 @@ class QuotaSetsController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
def show(self, req, id):
return self._show(req, id, [])
@wsgi.Controller.api_version( # noqa
MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@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')
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)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75')
def show(self, req, id): # noqa
return self._show(req, id, FILTERED_QUOTAS_2_57)
@validation.query_schema(quota_sets.query_schema_275, '2.75')
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
def _show(self, req, id, filtered_quotas):
context = req.environ['nova.context']
context.can(qs_policies.POLICY_ROOT % 'show', {'project_id': id})
@ -136,22 +137,24 @@ class QuotaSetsController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
def detail(self, req, id):
return self._detail(req, id, [])
@wsgi.Controller.api_version( # noqa
MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@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)
@validation.query_schema(quota_sets.query_schema_275, '2.75')
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
def _detail(self, req, id, filtered_quotas):
context = req.environ['nova.context']
context.can(qs_policies.POLICY_ROOT % 'detail', {'project_id': id})
@ -169,21 +172,21 @@ class QuotaSetsController(wsgi.Controller):
def update(self, req, id, body):
return self._update(req, id, body, [])
@wsgi.Controller.api_version( # noqa
MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@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_v275, '2.75')
def update(self, req, id, body): # noqa
return self._update(req, id, body, FILTERED_QUOTAS_2_57)
@validation.query_schema(quota_sets.query_schema_275, '2.75')
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
def _update(self, req, id, body, filtered_quotas):
context = req.environ['nova.context']
context.can(qs_policies.POLICY_ROOT % 'update', {'project_id': id})
@ -248,17 +251,19 @@ class QuotaSetsController(wsgi.Controller):
@wsgi.Controller.api_version("2.0", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(400)
@validation.query_schema(quota_sets.defaults_query)
def defaults(self, req, id):
return self._defaults(req, id, [])
@wsgi.Controller.api_version( # noqa
MIN_WITHOUT_PROXY_API_SUPPORT_VERSION, '2.56')
@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)
@ -275,8 +280,8 @@ class QuotaSetsController(wsgi.Controller):
# +microversions because the resource quota-set has been deleted completely
# when returning a response.
@wsgi.expected_errors(())
@validation.query_schema(quota_sets.query_schema_275, '2.75')
@validation.query_schema(quota_sets.query_schema, '2.0', '2.74')
@validation.query_schema(quota_sets.show_query_v275, '2.75')
@validation.query_schema(quota_sets.show_query, '2.0', '2.74')
@wsgi.response(202)
def delete(self, req, id):
context = req.environ['nova.context']

View File

@ -0,0 +1,25 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -14,5 +14,6 @@
# been removed
create = {}
update = {}
index_query = {}

View File

@ -124,3 +124,17 @@ set_metadata = {
'required': ['set_metadata'],
'additionalProperties': False,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -50,3 +50,17 @@ create = {
create_v249 = copy.deepcopy(create)
create_v249['properties']['interfaceAttachment'][
'properties']['tag'] = parameter_types.tag
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -0,0 +1,22 @@
# Copyright 2014 IBM Corporation. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
detail_query = index_query

View File

@ -14,7 +14,8 @@
# deprecated proxy APIs
create = {}
add_interface = {}
remove_interface = {}
index_query = {}
show_query = {}

View File

@ -16,3 +16,9 @@
create = {}
update = {}
sync_instances = {}
index_query = {}
detail_query = {}
info_query = {}
capacities_query = {}
show_query = {}

View File

@ -14,3 +14,5 @@
# been removed
create = {}
show_query = {}

View File

@ -15,3 +15,5 @@
create = {}
update = {}
index_query = {}

View File

@ -0,0 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -14,3 +14,6 @@
# been removed
create = {}
index_query = {}
show_query = {}

View File

@ -0,0 +1,25 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -14,5 +14,6 @@
# been removed
reserve = {}
unreserve = {}
show_query = {}

View File

@ -50,3 +50,10 @@ remove_tenant_access = {
'required': ['removeTenantAccess'],
'additionalProperties': False,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -138,3 +138,10 @@ index_query = {
index_query_275 = copy.deepcopy(index_query)
index_query_275['additionalProperties'] = False
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -36,3 +36,17 @@ update.update({
'minProperties': 1,
'maxProperties': 1
})
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -14,3 +14,6 @@
# been removed
update = {}
index_query = {}
show_query = {}

View File

@ -0,0 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -56,3 +56,8 @@ remove_floating_ip = {
'required': ['removeFloatingIp'],
'additionalProperties': False
}
# NOTE(stephenfin): These schemas are intentionally empty since these APIs are
# deprecated proxy APIs
show_query = {}
index_query = {}

View File

@ -15,3 +15,6 @@
create = {}
update = {}
index_query = {}
show_query = {}

View File

@ -0,0 +1,17 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# NOTE(stephenfin): These schemas are intentionally empty since these APIs have
# been removed
index_query = {}
show_query = {}

View File

@ -48,3 +48,10 @@ index_query = {
# do not to update the additionalProperties to False.
'additionalProperties': True
}
# NOTE(stephenfin): These schemas are intentionally empty since these APIs are
# deprecated proxy APIs
startup_query = {}
shutdown_query = {}
reboot_query = {}
show_query = {}

View File

@ -14,7 +14,13 @@
from nova.api.validation import parameter_types
list_query_schema_v233 = {
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
index_query_v233 = {
'type': 'object',
'properties': parameter_types.pagination_parameters,
# NOTE(gmann): This is kept True to keep backward compatibility.
@ -24,7 +30,7 @@ list_query_schema_v233 = {
'additionalProperties': True
}
list_query_schema_v253 = {
index_query_v253 = {
'type': 'object',
'properties': {
# The 2.33 microversion added support for paging by limit and marker.
@ -42,7 +48,13 @@ list_query_schema_v253 = {
'additionalProperties': False
}
show_query_schema_v253 = {
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
show_query_v253 = {
'type': 'object',
'properties': {
'with_servers': parameter_types.single_param(
@ -50,3 +62,10 @@ show_query_schema_v253 = {
},
'additionalProperties': False
}
# NOTE(stephenfin): These schemas are intentionally empty since these APIs are
# deprecated
statistics_query = {}
search_query = {}
servers_query = {}
uptime_query = {}

View File

@ -42,3 +42,9 @@ update = {
}
update_all = create
# NOTE(stephenfin): These schemas are intentionally empty since these APIs have
# been removed
index_query = {}
show_query = {}

View File

@ -0,0 +1,52 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nova.api.validation import parameter_types
# NOTE(stephenfin): These schemas are incomplete but won't be enhanced further
# since these APIs have been removed
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
index_query = {
'type': 'object',
'properties': {
# NOTE(stephenfin): We never validated these and we're not going to add
# that validation now.
# field filters
'name': {},
'status': {},
'changes-since': {},
'server': {},
'type': {},
'minRam': {},
'minDisk': {},
# pagination filters
'limit': parameter_types.multi_params(
parameter_types.positive_integer),
'page_size': parameter_types.multi_params(
parameter_types.positive_integer),
'marker': {},
'offset': parameter_types.multi_params(
parameter_types.positive_integer),
},
'patternProperties': {
'^property-.*$': {},
},
'additionalProperties': True,
}
detail_query = index_query

View File

@ -16,7 +16,13 @@ import copy
from nova.api.validation import parameter_types
list_query_params_v258 = {
list_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
list_query_v258 = {
'type': 'object',
'properties': {
# The 2.58 microversion added support for paging by limit and marker
@ -30,8 +36,14 @@ list_query_params_v258 = {
'additionalProperties': False
}
list_query_params_v266 = copy.deepcopy(list_query_params_v258)
list_query_params_v266['properties'].update({
list_query_v266 = copy.deepcopy(list_query_v258)
list_query_v266['properties'].update({
'changes-before': parameter_types.single_param(
{'type': 'string', 'format': 'date-time'}),
})
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -0,0 +1,17 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# NOTE(stephenfin): These schemas are intentionally empty since these APIs have
# been removed
index_query = {}
show_query = {}

View File

@ -16,3 +16,6 @@
create = {}
add = {}
disassociate = {}
index_query = {}
show_query = {}

View File

@ -45,3 +45,10 @@ del update_v257['properties']['quota_class_set']['properties'][
'injected_file_content_bytes']
del update_v257['properties']['quota_class_set']['properties'][
'injected_file_path_bytes']
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -80,7 +80,7 @@ del update_quota_set_v257['injected_file_path_bytes']
update_v257 = copy.deepcopy(update_v236)
update_v257['properties']['quota_set']['properties'] = update_quota_set_v257
query_schema = {
show_query = {
'type': 'object',
'properties': {
'user_id': parameter_types.multi_params({'type': 'string'})
@ -92,5 +92,12 @@ query_schema = {
'additionalProperties': True
}
query_schema_275 = copy.deepcopy(query_schema)
query_schema_275['additionalProperties'] = False
show_query_v275 = copy.deepcopy(show_query)
show_query_v275['additionalProperties'] = False
# TODO(stephenfin): Remove additionalProperties in a future API version
defaults_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -14,3 +14,6 @@
# been removed
create = {}
show_query = {}
index_query = {}

View File

@ -77,6 +77,13 @@ create_rules = {
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
index_query = {
'type': 'object',
'properties': {
@ -93,6 +100,12 @@ index_query = {
'additionalProperties': True
}
# TODO(stephenfin): Remove additionalProperties in a future API version
server_sg_index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
add_security_group = {

View File

@ -0,0 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -77,7 +77,7 @@ sg_properties['properties']['rules'] = {
'additionalProperties': False,
}
server_groups_query_param = {
index_query = {
'type': 'object',
'properties': {
'all_projects': parameter_types.multi_params({'type': 'string'}),
@ -91,5 +91,11 @@ server_groups_query_param = {
'additionalProperties': True
}
server_groups_query_param_275 = copy.deepcopy(server_groups_query_param)
server_groups_query_param_275['additionalProperties'] = False
index_query_v275 = copy.deepcopy(index_query)
index_query_v275['additionalProperties'] = False
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -49,3 +49,17 @@ update_all = {
'required': ['metadata'],
'additionalProperties': False,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
force_complete = {
'type': 'object',
'properties': {
@ -24,3 +23,17 @@ force_complete = {
'required': ['force_complete'],
'additionalProperties': False,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -0,0 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -31,3 +31,17 @@ update = {
"title": "Server tag",
"type": "null",
}
# TODO(stephenfin): Remove additionalProperties in a future API version
index_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -0,0 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
query_params_v21 = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -738,3 +738,9 @@ query_params_v275['properties'].update({
# 2. Make 'additionalProperties' False.
query_params_v275['additionalProperties'] = False
# *****Schema updates for microversion 2.75 end here*******
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -14,3 +14,6 @@
# been removed
create = {}
index_query = {}
show_query = {}

View File

@ -0,0 +1,25 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}
# TODO(stephenfin): Remove additionalProperties in a future API version
multi_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -0,0 +1,16 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# NOTE(stephenfin): These schemas are intentionally empty since these APIs have
# been removed
index_query = {}

View File

@ -0,0 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True,
}

View File

@ -144,3 +144,17 @@ detail_query = index_query
index_query_275 = copy.deepcopy(index_query)
index_query_275['additionalProperties'] = False
# TODO(stephenfin): Remove additionalProperties in a future API version
show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True
}
# TODO(stephenfin): Remove additionalProperties in a future API version
snapshot_show_query = {
'type': 'object',
'properties': {},
'additionalProperties': True
}

View File

@ -37,6 +37,7 @@ class SecurityGroupDefaultRulesController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('21.0.0', _removal_reason)
@validation.query_schema(schema.show_query)
def show(self, req, id):
raise exc.HTTPGone()
@ -47,5 +48,6 @@ class SecurityGroupDefaultRulesController(wsgi.Controller):
@wsgi.expected_errors(410)
@wsgi.removed('21.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req):
raise exc.HTTPGone()

View File

@ -136,6 +136,7 @@ class SecurityGroupController(SecurityGroupControllerBase, wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((400, 404))
@validation.query_schema(schema.show_query)
def show(self, req, id):
"""Return data about the given security group."""
context = req.environ['nova.context']
@ -354,6 +355,7 @@ class ServerSecurityGroupController(
):
@wsgi.expected_errors(404)
@validation.query_schema(schema.server_sg_index_query)
def index(self, req, server_id):
"""Returns a list of security groups for the given instance."""
context = req.environ['nova.context']

View File

@ -17,8 +17,10 @@ import webob
from nova.api.openstack import api_version_request
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import server_diagnostics as schema
from nova.api.openstack.compute.views import server_diagnostics
from nova.api.openstack import wsgi
from nova.api import validation
from nova.compute import api as compute
from nova import exception
from nova.policies import server_diagnostics as sd_policies
@ -32,6 +34,7 @@ class ServerDiagnosticsController(wsgi.Controller):
self.compute_api = compute.API()
@wsgi.expected_errors((400, 404, 409, 501))
@validation.query_schema(schema.index_query)
def index(self, req, server_id):
context = req.environ["nova.context"]
instance = common.get_instance(self.compute_api, context, server_id)

View File

@ -119,6 +119,7 @@ class ServerGroupController(wsgi.Controller):
return server_group
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id):
"""Return data about the given server group."""
context = req.environ['nova.context']
@ -147,8 +148,8 @@ class ServerGroupController(wsgi.Controller):
raise webob.exc.HTTPNotFound(explanation=e.format_message())
@wsgi.expected_errors(())
@validation.query_schema(schema.server_groups_query_param_275, '2.75')
@validation.query_schema(schema.server_groups_query_param, '2.0', '2.74')
@validation.query_schema(schema.index_query, '2.0', '2.74')
@validation.query_schema(schema.index_query_v275, '2.75')
def index(self, req):
"""Returns a list of server groups."""
context = req.environ['nova.context']

View File

@ -48,6 +48,7 @@ class ServerMetadataController(wsgi.Controller):
return meta_dict
@wsgi.expected_errors(404)
@validation.query_schema(server_metadata.index_query)
def index(self, req, server_id):
"""Returns the list of metadata for a given instance."""
context = req.environ['nova.context']
@ -123,6 +124,7 @@ class ServerMetadataController(wsgi.Controller):
'update metadata', server.uuid)
@wsgi.expected_errors(404)
@validation.query_schema(server_metadata.show_query)
def show(self, req, server_id, id):
"""Return a single metadata item."""
context = req.environ['nova.context']

View File

@ -92,6 +92,7 @@ class ServerMigrationsController(wsgi.Controller):
@wsgi.Controller.api_version("2.23")
@wsgi.expected_errors(404)
@validation.query_schema(server_migrations.index_query)
def index(self, req, server_id):
"""Return all migrations of an instance in progress."""
context = req.environ['nova.context']
@ -114,6 +115,7 @@ class ServerMigrationsController(wsgi.Controller):
@wsgi.Controller.api_version("2.23")
@wsgi.expected_errors(404)
@validation.query_schema(server_migrations.show_query)
def show(self, req, server_id, id):
"""Return the migration of an instance in progress by id."""
context = req.environ['nova.context']

View File

@ -17,7 +17,9 @@
from nova.api.metadata import password
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import server_password as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova.compute import api as compute
from nova.policies import server_password as sp_policies
@ -30,6 +32,7 @@ class ServerPasswordController(wsgi.Controller):
self.compute_api = compute.API()
@wsgi.expected_errors(404)
@validation.query_schema(schema.index_query)
def index(self, req, server_id):
context = req.environ['nova.context']
instance = common.get_instance(self.compute_api, context, server_id)

View File

@ -63,6 +63,7 @@ class ServerTagsController(wsgi.Controller):
@wsgi.Controller.api_version("2.26")
@wsgi.response(204)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, server_id, id):
context = req.environ["nova.context"]
im = _get_instance_mapping(context, server_id)
@ -82,6 +83,7 @@ class ServerTagsController(wsgi.Controller):
@wsgi.Controller.api_version("2.26")
@wsgi.expected_errors(404)
@validation.query_schema(schema.index_query)
def index(self, req, server_id):
context = req.environ["nova.context"]
im = _get_instance_mapping(context, server_id)

View File

@ -12,7 +12,9 @@
# under the License.
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import server_topology as schema
from nova.api.openstack import wsgi
from nova.api import validation
from nova.compute import api as compute
from nova.policies import server_topology as st_policies
@ -25,6 +27,7 @@ class ServerTopologyController(wsgi.Controller):
@wsgi.Controller.api_version("2.78")
@wsgi.expected_errors(404)
@validation.query_schema(schema.query_params_v21)
def index(self, req, server_id):
context = req.environ["nova.context"]
instance = common.get_instance(self.compute_api, context, server_id,

View File

@ -459,6 +459,7 @@ class ServersController(wsgi.Controller):
return objects.NetworkRequestList(objects=networks)
@wsgi.expected_errors(404)
@validation.query_schema(schema_servers.show_query)
def show(self, req, id):
"""Returns server details by server id."""
context = req.environ['nova.context']

View File

@ -76,6 +76,7 @@ class TenantNetworkController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
def index(self, req):
context = req.environ['nova.context']
context.can(tn_policies.POLICY_NAME % 'list',
@ -88,6 +89,7 @@ class TenantNetworkController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id):
context = req.environ['nova.context']
context.can(tn_policies.POLICY_NAME % 'show',

View File

@ -14,8 +14,10 @@
# under the License.
from nova.api.openstack import api_version_request
from nova.api.openstack.compute.schemas import versions as schema
from nova.api.openstack.compute.views import versions as views_versions
from nova.api.openstack import wsgi
from nova.api import validation
LINKS = {
@ -80,12 +82,14 @@ class Versions(wsgi.Resource):
def __init__(self):
super(Versions, self).__init__(None)
@validation.query_schema(schema.show_query)
def index(self, req, body=None):
"""Return all versions."""
builder = views_versions.get_view_builder(req)
return builder.build_versions(VERSIONS)
@wsgi.response(300)
@validation.query_schema(schema.multi_query)
def multi(self, req, body=None):
"""Return multiple choices."""
builder = views_versions.get_view_builder(req)
@ -107,6 +111,7 @@ class VersionsV2(wsgi.Resource):
def __init__(self):
super(VersionsV2, self).__init__(None)
@validation.query_schema(schema.show_query)
def index(self, req, body=None):
builder = views_versions.get_view_builder(req)
ver = 'v2.0' if req.is_legacy_v2() else 'v2.1'

View File

@ -15,13 +15,17 @@
import webob.exc
from nova.api.openstack.compute.schemas import versions as schema
from nova.api.openstack.compute import versions
from nova.api.openstack.compute.views import versions as views_versions
from nova.api.openstack import wsgi
from nova.api import validation
class VersionsController(wsgi.Controller):
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
def show(self, req, id='v2.1'):
builder = views_versions.get_view_builder(req)
if req.is_legacy_v2():

View File

@ -17,7 +17,9 @@
from webob import exc
from nova.api.openstack.compute.schemas import virtual_interfaces as schema
from nova.api.openstack import wsgi
from nova.api import validation
_removal_reason = """\
This API only works with *nova-network*, which was deprecated in the
@ -31,5 +33,6 @@ class ServerVirtualInterfaceController(wsgi.Controller):
@wsgi.expected_errors((410))
@wsgi.removed('18.0.0', _removal_reason)
@validation.query_schema(schema.index_query)
def index(self, req, server_id):
raise exc.HTTPGone()

View File

@ -22,6 +22,7 @@ from nova.api.openstack import api_version_request
from nova.api.openstack.api_version_request \
import MAX_PROXY_API_SUPPORT_VERSION
from nova.api.openstack import common
from nova.api.openstack.compute.schemas import volume_attachment as volume_attachment_schema # noqa: E501
from nova.api.openstack.compute.schemas import volumes as volumes_schema
from nova.api.openstack import wsgi
from nova.api import validation
@ -110,6 +111,7 @@ class VolumeController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(404)
@validation.query_schema(volumes_schema.show_query)
def show(self, req, id):
"""Return data about the given volume."""
context = req.environ['nova.context']
@ -140,8 +142,8 @@ class VolumeController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=e.format_message())
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@validation.query_schema(volumes_schema.index_query)
@wsgi.expected_errors(())
@validation.query_schema(volumes_schema.index_query)
def index(self, req):
"""Returns a summary list of volumes."""
context = req.environ['nova.context']
@ -150,8 +152,8 @@ class VolumeController(wsgi.Controller):
return self._items(req, entity_maker=_translate_volume_summary_view)
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@validation.query_schema(volumes_schema.detail_query)
@wsgi.expected_errors(())
@validation.query_schema(volumes_schema.detail_query)
def detail(self, req):
"""Returns a detailed list of volumes."""
context = req.environ['nova.context']
@ -327,6 +329,7 @@ class VolumeAttachmentController(wsgi.Controller):
return {'volumeAttachments': results}
@wsgi.expected_errors(404)
@validation.query_schema(volume_attachment_schema.show_query)
def show(self, req, server_id, id):
"""Return data about the given volume attachment."""
context = req.environ['nova.context']
@ -607,6 +610,7 @@ class SnapshotController(wsgi.Controller):
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(404)
@validation.query_schema(volumes_schema.snapshot_show_query)
def show(self, req, id):
"""Return data about the given snapshot."""
context = req.environ['nova.context']
@ -635,8 +639,8 @@ class SnapshotController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=e.format_message())
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@validation.query_schema(volumes_schema.index_query)
@wsgi.expected_errors(())
@validation.query_schema(volumes_schema.index_query)
def index(self, req):
"""Returns a summary list of snapshots."""
context = req.environ['nova.context']
@ -645,8 +649,8 @@ class SnapshotController(wsgi.Controller):
return self._items(req, entity_maker=_translate_snapshot_summary_view)
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@validation.query_schema(volumes_schema.detail_query)
@wsgi.expected_errors(())
@validation.query_schema(volumes_schema.detail_query)
def detail(self, req):
"""Returns a detailed list of snapshots."""
context = req.environ['nova.context']

View File

@ -140,9 +140,6 @@ class FlavorAccessTestV21(test.NoDBTestCase):
self.stub_out('nova.api.openstack.identity.verify_project_id',
lambda ctx, project_id: True)
self.req = FakeRequest()
self.req.environ = {"nova.context": context.RequestContext(
'fake_user', fakes.FAKE_PROJECT_ID)}
self.stub_out('nova.objects.Flavor._flavor_get_by_flavor_id_from_db',
fake_get_flavor_by_flavor_id)
self.stub_out('nova.objects.flavor._flavor_get_all_from_db',
@ -163,16 +160,24 @@ class FlavorAccessTestV21(test.NoDBTestCase):
@mock.patch('nova.objects.Flavor._flavor_get_by_flavor_id_from_db',
side_effect=exception.FlavorNotFound(flavor_id='foo'))
def test_list_flavor_access_public(self, mock_api_get):
req = fakes.HTTPRequest.blank(
self._prefix + '/flavors/1/os-flavor-access')
req.environ = {"nova.context": context.RequestContext(
'fake_user', fakes.FAKE_PROJECT_ID)}
# query os-flavor-access on public flavor should return 404
self.assertRaises(exc.HTTPNotFound,
self.flavor_access_controller.index,
self.req, '1')
req, '1')
def test_list_flavor_access_private(self):
req = fakes.HTTPRequest.blank(
self._prefix + '/flavors/2/os-flavor-access')
req.environ = {"nova.context": context.RequestContext(
'fake_user', fakes.FAKE_PROJECT_ID)}
expected = {'flavor_access': [
{'flavor_id': '2', 'tenant_id': 'proj2'},
{'flavor_id': '2', 'tenant_id': 'proj3'}]}
result = self.flavor_access_controller.index(self.req, '2')
result = self.flavor_access_controller.index(req, '2')
self.assertEqual(result, expected)
def test_list_flavor_with_admin_default_proj1(self):
@ -300,10 +305,14 @@ class FlavorAccessTestV21(test.NoDBTestCase):
project_id=projectid)
self.stub_out('nova.objects.Flavor._flavor_add_project',
stub_add_flavor_access)
req = fakes.HTTPRequest.blank(
self._prefix + '/flavors/3/os-flavor-access')
req.environ = {"nova.context": context.RequestContext(
'fake_user', fakes.FAKE_PROJECT_ID)}
body = {'addTenantAccess': {'tenant': 'proj2'}}
self.assertRaises(exc.HTTPConflict,
self.flavor_action_controller._add_tenant_access,
self.req, '3', body=body)
req, '3', body=body)
def test_remove_tenant_access_with_bad_access(self):
def stub_remove_flavor_access(context, flavorid, projectid):
@ -312,9 +321,13 @@ class FlavorAccessTestV21(test.NoDBTestCase):
self.stub_out('nova.objects.Flavor._flavor_del_project',
stub_remove_flavor_access)
body = {'removeTenantAccess': {'tenant': 'proj2'}}
req = fakes.HTTPRequest.blank(
self._prefix + '/flavors/3/os-flavor-access')
req.environ = {"nova.context": context.RequestContext(
'fake_user', fakes.FAKE_PROJECT_ID)}
self.assertRaises(exc.HTTPNotFound,
self.flavor_action_controller._remove_tenant_access,
self.req, '3', body=body)
req, '3', body=body)
def test_add_tenant_access_is_public(self):
body = {'addTenantAccess': {'tenant': 'proj2'}}