Filter Allocation Candidates by Provider Tree¶
https://blueprints.launchpad.net/nova/+spec/alloc-candidates-in-tree
This blueprint proposes to support for filtering allocation candidates by provider tree.
Problem description¶
Placement currently supports in_tree
query parameters for the
GET /resource_providers
endpoints. This parameter is a string representing
a resource provider uuid, and when this is present, the response is limited to
resource providers within the same tree of the provider indicated by the uuid.
See Nested Resource Providers spec for details.
However, GET /allocation_candidates
doesn’t support the in_tree
query
parameter to filter the allocation candidates by resource tree. This results
in inefficient post-processing in some cases where the caller has already
selected the resource provider tree before calling that API.
Use Cases¶
This feature is useful when the caller of the GET /allocation_candidates
has already picked up resource providers they want to use.
As described in the Bug#1777591, when an admin operator creates an instance on a specific host, nova now explicitly sets no limitation for getting allocation candidates to prevent placement from filtering out the pre-determined target resource provider by the random limitation. (For the limitation feature of the API, see the Limiting Allocation Candidates spec)
Instead of issuing the inefficient request to placement, we can use in_tree
query with the pre-determined target host resource provider uuid calling the
GET /allocation_candidates
API.
We would solve the same problem for cases of live migration to a specified host and rebuilding an instance on the same host.
Proposed change¶
The GET /allocation_candidates
call will accept a new query parameter
in_tree
. This parameter is a string representing a resource provider uuid.
When this is present, the only resource providers returned will be those in the
same tree with the given resource provider.
The numbered syntax in_tree<N>
is also supported. This restricts providers
satisfying the Nth granular request group to the tree of the specified
provider. This may be redundant with other in_tree<N>
values specified in
other groups (including the unnumbered group). However, it can be useful in
cases where a specific resource (e.g. DISK_GB) needs to come from a specific
sharing provider (e.g. shared storage).
In the following environments,
+-----------------------+ +-----------------------+
| sharing storage (ss1) | | sharing storage (ss2) |
| DISK_GB: 1000 | | DISK_GB: 1000 |
+-----------+-----------+ +-----------+-----------+
| |
+-----------------+----------------+
|
| Shared via an aggregate
+-----------------+----------------+
| |
+--------------|---------------+ +--------------|--------------+
| +------------+-------------+ | | +------------+------------+ |
| | compute node (cn1) | | | |compute node (cn2) | |
| | DISK_GB: 1000 | | | | DISK_GB: 1000 | |
| +-----+-------------+------+ | | +----+-------------+------+ |
| | nested | nested | | | nested | nested |
| +-----+------+ +----+------+ | | +----+------+ +----+------+ |
| | numa1_1 | | numa1_2 | | | | numa2_1 | | numa2_2 | |
| | VCPU: 4 | | VCPU: 4 | | | | VCPU: 4 | | VCPU: 4 | |
| +------------+ +-----------+ | | +-----------+ +-----------+ |
+------------------------------+ +-----------------------------+
for example:
GET /allocation_candidates?resources=VCPU:1,DISK_GB:50&in_tree={cn1_uuid}
will return 2 combinations of allocation candidates.
result A:
1. numa1_1 (VCPU) + cn1 (DISK_GB)
2. numa1_2 (VCPU) + cn1 (DISK_GB)
The specified tree can be a non-root provider:
GET /allocation_candidates?resources=VCPU:1,DISK_GB:50&in_tree={numa1_1_uuid}
will return the same result.
result B:
1. numa1_1 (VCPU) + cn1 (DISK_GB)
2. numa1_2 (VCPU) + cn1 (DISK_GB)
When you want to have VCPU
from cn1
and DISK_GB
from wherever,
the request may look like:
GET /allocation_candidates?resources=VCPU:1&in_tree={cn1_uuid}
&resources1=DISK_GB:10
which will return the sharing providers as well.
result C:
1. numa1_1 (VCPU) + cn1 (DISK_GB)
2. numa1_2 (VCPU) + cn1 (DISK_GB)
3. numa1_1 (VCPU) + ss1 (DISK_GB)
4. numa1_2 (VCPU) + ss1 (DISK_GB)
5. numa1_1 (VCPU) + ss2 (DISK_GB)
6. numa1_2 (VCPU) + ss2 (DISK_GB)
When you want to have VCPU
from wherever and DISK_GB
from ss1
,
the request may look like:
GET: /allocation_candidates?resources=VCPU:1
&resources1=DISK_GB:10&in_tree1={ss1_uuid}
which will stick to the first sharing provider for DISK_GB.
result D:
1. numa1_1 (VCPU) + ss1 (DISK_GB)
2. numa1_2 (VCPU) + ss1 (DISK_GB)
3. numa2_1 (VCPU) + ss1 (DISK_GB)
4. numa2_2 (VCPU) + ss1 (DISK_GB)
When you want to have VCPU
from cn1
and DISK_GB
from ss1
,
the request may look like:
GET: /allocation_candidates?resources1=VCPU:1&in_tree1={cn1_uuid}
&resources2=DISK_GB:10&in_tree2={ss1_uuid}
&group_policy=isolate
which will return only 2 candidates.
result E:
1. numa1_1 (VCPU) + ss1 (DISK_GB)
2. numa1_2 (VCPU) + ss1 (DISK_GB)
Alternatives¶
Alternative 1:
We could mitigate the restriction to include sharing providers assuming that they are in specified non-sharing tree that shares them. For example, we could change result A to return:
1. numa1_1 (VCPU) + cn1 (DISK_GB)
2. numa1_2 (VCPU) + cn1 (DISK_GB)
3. numa1_1 (VCPU) + ss1 (DISK_GB)
4. numa1_2 (VCPU) + ss1 (DISK_GB)
5. numa1_1 (VCPU) + ss2 (DISK_GB)
6. numa1_2 (VCPU) + ss2 (DISK_GB)
This is possible if we assume that ss1
and ss2
are in “an expanded
concept of a tree” of cn1
, but we don’t take this way because we can get
the same result using the granular request. Different result for a different
request means we support more use cases than the same result for a different
request.
Alternative 2:
In result B, we could exclude numa1_2
resource provider (the second
candidate), but we don’t take this way for the following reason:
It is not consistent with the existing in_tree
behavior in
GET /resource_providers
. The inconsistency despite of the same queryparam
name could confuse users. If we need this behaivor, that would be something
like subtree
queryparam which should be symmetrically implemented to
GET /resource_providers
as well. This is already proposed in
Support subtree filter for GET /resource_providers spec.
Data model impact¶
None.
REST API impact¶
A new microversion will be created to add the in_tree
parameter to
GET /allocation_candidates
API.
Security impact¶
None.
Notifications impact¶
None.
Other end user impact¶
None.
Performance Impact¶
If the callers of the GET /allocation_candidates
has already picked up
resource providers they want to use, they would get improved performance
using this new in_tree
query because we don’t need to get all the
candidates from the database.
Other deployer impact¶
This feature enables us to develop efficient query in nova for cases that is described in the Use Cases section.
Developer impact¶
None.
Upgrade impact¶
None.
Implementation¶
Assignee(s)¶
- Primary assignee:
Tetsuro Nakamura (nakamura.tetsuro@lab.ntt.co.jp)
Work Items¶
Update the
AllocationCandidates.get_by_requests
method to change the database queries to filter on the specified provider tree.Update the placement API handlers for
GET /allocation_candidates
in a new microversion to pass the newin_tree
parameter to the methods changed in the steps above, including input validation adjustments.Add functional tests of the modified database queries.
Add gabbi tests that express the new queries, both successful queries and those that should cause a 400 response.
Release note for the API change.
Update the microversion documents to indicate the new version.
Update placement-api-ref to show the new query handling.
Dependencies¶
None.
Testing¶
Normal functional and unit testing.
Documentation Impact¶
Document the REST API microversion in the appropriate reference docs.
References¶
Bug#1777591 reported in the launchpad