[placement] Support forbidden traits in API

In a new microversion (1.22) expose support for processing
forbidden traits in GET /resource_providers and GET
/allocation_candidates. A forbidden trait is expressed as
part of the required parameter with a "!" prefix:

    required=CUSTOM_FAST,!CUSTOM_SLOW

This change uses db and query processing code adjustments
already present in the code but guarded by a flag. If the
currently requested microversion matches 1.22 or beyond
that flag is True, otherwise False.

Reno, api-ref update and api history update are included.
Because this microversion changes the value of an existing
parameter it was unclear how to best express that in the
api-ref. In this case existing parameter references were
annotated.

Partially implements blueprint placement-forbidden-traits

Change-Id: I43e92bc5f97db7a2b09e64c6cb953c07d0561e63
This commit is contained in:
Chris Dent 2018-03-27 11:31:13 +01:00
parent 6f31523b31
commit 4e07d81260
9 changed files with 122 additions and 7 deletions

View File

@ -220,7 +220,11 @@ def list_allocation_candidates(req):
get_schema = schema.GET_SCHEMA_1_16
util.validate_query_params(req, get_schema)
requests = util.parse_qs_request_groups(req.GET)
# Control whether we handle forbidden traits.
allow_forbidden = want_version.matches((1, 22))
requests = util.parse_qs_request_groups(
req.GET, allow_forbidden=allow_forbidden)
limit = req.GET.getall('limit')
# JSONschema has already confirmed that limit has the form
# of an integer.

View File

@ -191,6 +191,8 @@ def list_resource_providers(req):
elif want_version.matches((1, 3)):
schema = rp_schema.GET_RPS_SCHEMA_1_3
allow_forbidden = want_version.matches((1, 22))
util.validate_query_params(req, schema)
filters = {}
@ -217,7 +219,8 @@ def list_resource_providers(req):
elif attr == 'resources':
value = util.normalize_resources_qs_param(value)
elif attr == 'required':
value = util.normalize_traits_qs_param(value)
value = util.normalize_traits_qs_param(
value, allow_forbidden=allow_forbidden)
filters[attr] = value
try:
resource_providers = rp_obj.ResourceProviderList.get_all_by_filters(

View File

@ -61,6 +61,8 @@ VERSIONS = [
'1.20', # Return 200 with provider payload from POST /resource_providers
'1.21', # Support ?member_of=<agg UUIDs> queryparam on
# GET /allocation_candidates
'1.22', # Support forbidden traits in the required parameter of
# GET /resource_providers and GET /allocation_candidates
]

View File

@ -261,3 +261,12 @@ Add support for the `member_of` query parameter to the `GET
aggregates. If this parameter is provided, the only resource providers returned
will be those in one of the specified aggregates that meet the other parts of
the request.
1.22 Support forbidden traits on resource providers and allocations candidates
------------------------------------------------------------------------------
Add support for expressing traits which are forbidden when filtering
``GET /resource_providers`` or ``GET /allocation_candidates``. A forbidden
trait is a properly formatted trait in the existing ``required`` parameter,
prefixed by a ``!``. For example ``required=!STORAGE_DISK_SSD`` asks that the
results not include any resource providers that provide solid state disk.

View File

@ -205,6 +205,14 @@ tests:
response_strings:
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,CUSTOM_MAGIC."
- name: get allocation candidates with empty required value 1.22
GET: /allocation_candidates?resources=VCPU:1,MEMORY_MB:1024,DISK_GB:100&required=
status: 400
request_headers:
openstack-api-version: placement 1.22
response_strings:
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,!CUSTOM_MAGIC."
- name: get allocation candidates with invalid required value
GET: /allocation_candidates?resources=VCPU:1,MEMORY_MB:1024,DISK_GB:100&required=,,
status: 400
@ -234,6 +242,19 @@ tests:
- HW_CPU_X86_SSE
- HW_CPU_X86_SSE2
- name: get allocation candidates with forbidden trait
GET: /allocation_candidates?resources=VCPU:1,MEMORY_MB:1024,DISK_GB:100&required=!HW_CPU_X86_SSE
status: 200
request_headers:
openstack-api-version: placement 1.22
response_json_paths:
# There are no allocations for CN1
$.allocation_requests.`len`: 1
$.allocation_requests[0].allocations.`len`: 2
$.allocation_requests[0].allocations["$ENVIRON['CN2_UUID']"].resources.VCPU: 1
$.allocation_requests[0].allocations["$ENVIRON['CN2_UUID']"].resources.MEMORY_MB: 1024
$.allocation_requests[0].allocations["$ENVIRON['SS_UUID']"].resources.DISK_GB: 100
- name: get allocation candidates with multiple required traits
GET: /allocation_candidates?resources=VCPU:1,MEMORY_MB:1024,DISK_GB:100&required=HW_CPU_X86_SSE,HW_CPU_X86_SSE2
status: 200

View File

@ -39,13 +39,13 @@ tests:
response_json_paths:
$.errors[0].title: Not Acceptable
- name: latest microversion is 1.21
- name: latest microversion is 1.22
GET: /
request_headers:
openstack-api-version: placement latest
response_headers:
vary: /openstack-api-version/
openstack-api-version: placement 1.21
openstack-api-version: placement 1.22
- name: other accept header bad version
GET: /

View File

@ -463,6 +463,59 @@ tests:
# Only RP_UUID satisfies both the tree and trait constraint
$.resource_providers[?uuid="$ENVIRON['RP_UUID']"].root_provider_uuid: $ENVIRON['PARENT_PROVIDER_UUID']
- name: list providers for full count
GET: /resource_providers
response_json_paths:
$.resource_providers.`len`: 3
- name: list providers forbidden 1.22
GET: /resource_providers?required=!STORAGE_DISK_SSD
response_json_paths:
$.resource_providers.`len`: 1
- name: confirm forbidden trait not there
GET: /resource_providers/$RESPONSE['$.resource_providers[0].uuid']/traits
response_json_paths:
$.traits: []
- name: list providers forbidden 1.21
GET: /resource_providers?required=!STORAGE_DISK_SSD
request_headers:
openstack-api-version: placement 1.21
status: 400
response_strings:
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,CUSTOM_MAGIC. Got: !STORAGE_DISK_SSD"
- name: list providers forbidden again
GET: /resource_providers?required=!MISC_SHARES_VIA_AGGREGATE
response_json_paths:
$.resource_providers.`len`: 2
- name: mixed required and forbidden
GET: /resource_providers?required=!HW_CPU_X86_SGX,STORAGE_DISK_SSD
response_json_paths:
$.resource_providers.`len`: 1
- name: confirm mixed required and forbidden
GET: /resource_providers/$RESPONSE['$.resource_providers[0].uuid']/traits
response_json_paths:
$.traits.`sorted`: ['MISC_SHARES_VIA_AGGREGATE', 'STORAGE_DISK_SSD']
- name: multiple forbidden
GET: /resource_providers?required=!MISC_SHARES_VIA_AGGREGATE,!HW_CPU_X86_SGX
response_json_paths:
$.resource_providers.`len`: 1
- name: confirm multiple forbidden
GET: /resource_providers/$RESPONSE['$.resource_providers[0].uuid']/traits
response_json_paths:
$.traits: []
- name: forbidden no apply
GET: /resource_providers?required=!HW_CPU_X86_VMX
response_json_paths:
$.resource_providers.`len`: 3
- name: create some inventory
PUT: /resource_providers/$ENVIRON['ALT_PARENT_PROVIDER_UUID']/inventories
request_headers:
@ -492,6 +545,16 @@ tests:
- name: invalid 'required' parameter - blank
GET: /resource_providers?required=
status: 400
response_strings:
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,!CUSTOM_MAGIC."
response_json_paths:
$.errors[0].title: Bad Request
- name: invalid 'required' parameter 1.21
GET: /resource_providers?required=
request_headers:
openstack-api-version: placement 1.21
status: 400
response_strings:
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,CUSTOM_MAGIC."
response_json_paths:
@ -501,7 +564,7 @@ tests:
GET: /resource_providers?required=STORAGE_DISK_SSD,,MISC_SHARES_VIA_AGGREGATE
status: 400
response_strings:
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,CUSTOM_MAGIC."
- "Invalid query string parameters: Expected 'required' parameter value of the form: HW_CPU_X86_VMX,!CUSTOM_MAGIC."
response_json_paths:
$.errors[0].title: Bad Request

View File

@ -59,7 +59,9 @@ allocation_candidates_required:
Accepts a list of comma-separated traits. Allocation requests in the
response will be for resource providers that have capacity for all
requested resources and the set of those resource providers will
*collectively* contain all of the required traits.
*collectively* contain all of the required traits. **Starting from
microversion 1.22** traits which are forbidden from any resource provider
may be expressed by prefixing a trait with a ``!``.
member_of:
type: string
in: query
@ -91,7 +93,9 @@ resource_provider_required_query:
required: false
description: >
A comma-delimited list of string trait names. Results will be filtered to
include only resource providers having all the specified traits.
include only resource providers having all the specified traits. **Starting
from microversion 1.22** traits which are forbidden from any resource
provider may be expressed by prefixing a trait with a ``!``.
min_version: 1.18
resource_provider_tree_query:
type: string

View File

@ -0,0 +1,9 @@
---
features:
- |
Placement microversion '1.22' adds support for expressing traits which are
forbidden when filtering ``GET /resource_providers`` or ``GET
/allocation_candidates``. A forbidden trait is a properly formatted trait
in the existing ``required`` parameter, prefixed by a ``!``. For example
``required=!STORAGE_DISK_SSD`` asks that the results not include any
resource providers that provide solid state disk.