Adjust the fixtures used by the functional tests so they
use placement database and web fixtures defined by placement
code. To avoid making redundant changes, the solely placement-
related unit and functional tests are removed, but the placement
code itself is not (yet).
openstack-placement is required by the functional tests. It is not
added to test-requirements as we do not want unit tests to depend
on placement in any way, and we enforce this by not having placement
in the test env.
The concept of tox-siblings is used to ensure that the
placement requirement will be satisfied correctly if there is a
depends-on. To make this happen, the functional jobs defined in
.zuul.yaml are updated to require openstack/placement.
tox.ini has to be updated to use a envdir that is the same
name as job. Otherwise the tox siblings role in ansible cannot work.
The handling of the placement fixtures is moved out of nova/test.py
into the functional tests that actually use it because we do not
want unit tests (which get the base test class out of test.py) to
have anything to do with placement. This requires adjusting some
test files to use absolute import.
Similarly, a test of the comparison function for the api samples tests
is moved into functional, because it depends on placement functionality,
TestUpgradeCheckResourceProviders in unit.cmd.test_status is moved into
a new test file: nova/tests/functional/test_nova_status.py. This is done
because it requires the PlacementFixture, which is only available to
functional tests. A MonkeyPatch is required in the test to make sure that
the right context managers are used at the right time in the command
itself (otherwise some tables do no exist). In the test itself, to avoid
speaking directly to the placement database, which would require
manipulating the RequestContext objects, resource providers are now
created over the API.
Co-Authored-By: Balazs Gibizer <balazs.gibizer@ericsson.com>
Change-Id: Idaed39629095f86d24a54334c699a26c218c6593
/reshaper provides a way to atomically modify some allocations and
inventory in a single transaction, allowing operations like migrating
some inventory from a parent provider to a new child.
A fair amount of code is reused from handler/inventory.py, some
refactoring is in order before things get too far with that.
In handler/allocation.py some code is extracted to its own methods
so it can be reused from reshaper.py.
This is done as microversion 1.30.
A suite of gabbi tests is provided which attempt to cover various
failures including schema violations, generation conflicts, and
data conflicts.
api-ref, release notes and rest history are updated
Change-Id: I5b33ac3572bc3789878174ffc86ca42ae8035cfa
Partially-Implements: blueprint reshape-provider-tree
This patch adds a microversion with a release note for allocation
candidates with nested resource provider trees.
From now on we support allocation candidates with nested resource
providers with the following features.
1) ``GET /allocation_candidates`` is aware of nested providers.
Namely, when provider trees are present, ``allocation_requests``
in the response of ``GET /allocation_candidates`` can include
allocations on combinations of multiple resource providers
in the same tree.
2) ``root_provider_uuid`` and ``parent_provider_uuid`` fields are
added to ``provider_summaries`` in the response of
``GET /allocation_candidates``.
Change-Id: I6cecb25c6c16cecc23d4008474d150b1f15f7d8a
Blueprint: nested-resource-providers-allocation-candidates
This patch adds new placement API microversion for handling consumer
generations.
Change-Id: I978fdea51f2d6c2572498ef80640c92ab38afe65
Co-Authored-By: Ed Leafe <ed@leafe.com>
Blueprint: add-consumer-generation
According to the spec [1] the version discovery doc must have a status
and links for each version. For the primary version the status value
should be 'CURRENT'. For placement the version discovery doc and "self"
are the same thing, so the provided "self" href looks redundant, but it
makes keystoneauth1 happy when doing version discovery.
In placement, since there is only one version at the moment, set status
to CURRENT.
Add a gabbi test that verifies the presence of both fields and values.
Without these fields, use of placement with a client that follows the
documented version discovery process will fail to work.
As the version doc is not considered microversioned[2] and in any case
this is making version discovery work where it didn't before, this is
not a candidate for a microversion and can be backported to the
beginning of placement's history if we like.
I've updated the api-ref docs. In the process I made the max
microversion in the sample discovery doc a bit more realistic and
in alignment with these modern times.
[1] http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html#version-discovery
[2] http://eavesdrop.openstack.org/irclogs/%23openstack-sdks/%23openstack-sdks.2018-06-13.log.html#t2018-06-13T13:40:12
Change-Id: Ie602ab1768efbf103563d8f6b9d28965fc81021a
Closes-Bug: #1776668
The response of ``GET /allocation_candidates`` API provides two fields
of ``allocation_requests`` and ``provider_summaries``. The callers,
like the filter scheduler in nova, would use information in
``provider_summaries`` in sorting or filtering providers to allocate
consumers. However, currently ``provider_summaries`` doesn't contain
resource classes that aren't requested.
With this patch, ``GET /allocation_candidates`` API returns all
resource classes with a new microversion.
Change-Id: Ic491f190ebd97d94c18931a0e78d779a55ee47a1
Closes-Bug: #1760276
Blueprint: placement-return-all-resources
This is needed for ironic use case, when during cleaning, resources
are reserved by ironic itself. Cyborg will also benefit from this
during FPGA programming.
blueprint: allow-reserved-equal-total-inventory
Change-Id: I037d9b8c1bb554c3437434cc9a57ddb630dd62f0
In a new microversion, the GET /allocation_candidates API now accepts
granular resource request syntax:
?resourcesN=...&requiredN=...&member_ofN=...&group_policy={isolate|none}
Change-Id: I4e99974443aa513fd9f837a6057f67d744caf1b4
blueprint: granular-resource-requests
Adds a new placement API microversion that supports specifying multiple
member_of parameters to the GET /resource_providers and GET
/allocation_candidates API endpoints.
When multiple member_of parameters are found, they are passed down to
the ResourceProviderList.get_by_filters() method as a list. Items in
this list are lists of aggregate UUIDs.
The list of member_of items is evaluated so that resource providers
matching ALL of the member_of constraints are returned.
When a member_of item contains multiple UUIDs, we look up resource
providers that have *any* of those aggregate UUIDs associated with them.
Change-Id: Ib4f1955f06f2159dfb221f3d2bc8ff7bfce71ee2
blueprint: alloc-candidates-member-of
The API-sig has a guideline[1] for including error codes in error
responses to help distinguish errors with the same status code
from one another. This change provides a simplest-thing-that-could-
possibly-work solution to make that go.
This solution comes about after a few different constraints and attempts:
* We would prefer to go on using the existing webob.exc exceptions, not
make subclasses.
* We already have a special wrapper around our wsgi apps to deal with
setting the json_error_formatter.
* Though webob allows custom Request and Response objects, it uses the
default Response object as the parent of the HTTP exceptions.
* The Response object accepts kwargs, but only if they can be associated
with known attributes on the class. Since we can't subclass...
* The json_error_formatter method is not passed the raw exception, but
it does get the current WSGI environ
* The webob.exc classes take a 'comment' kwarg that is not used, but
is also not passed to the json_error_formatter.
Therefore, when we raise an exception, we can set 'comment' to a code
and then assign that comment to a well known field in the environ and if
that environ is set in json_error_formatter, we can set 'code' in the
output.
This is done in a new microversion, 1.23. Every response gets a default
code 'placement.undefined_code' from 1.23 on. Future development will
add specific codes where required. This change adds a stub code for
inventory in use when doing a PUT to .../inventories but the name
may need improvement.
[1] http://specs.openstack.org/openstack/api-wg/guidelines/errors.html
Implements blueprint placement-api-error-handling
Change-Id: I9a833aa35d474caa35e640bbad6c436a3b16ac5e
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
That change extracts much of the microversion handling code from
placement and uses code from the microversion-parse library instead.
The code in microversion-parse was taken from placement and lightly
adjusted to make it more generally useful.
Depends-On: https://review.openstack.org/555332
Change-Id: I5a70ebf2843d2b50dccb44e66d50e1e5105005f4
The call to GET /allocation_candidates now accepts a 'member_of'
parameter, representing one or more aggregate UUIDs. If this parameter
is supplied, the allocation_candidates returned will be limited to those
with resource_providers that belong to at least one of the supplied
aggregates.
Blueprint: alloc-candidates-member-of
Change-Id: I5857e927a830914c96e040936804e322baccc24c
To facilitate opaqueness of resource provider generation internals, we
need to return the (initial) generation when a provider is created. For
consistency with other APIs, we will do this by returning the entire
resource provider record (which includes the generation) from POST
/resource_providers.
Change-Id: I8624e194fe0173531c5aa2119c903e3c68b8c6cd
blueprint: generation-from-create-provider
Placement API microversion 1.19 enhances the payloads for the `GET
/resource_providers/{uuid}/aggregates` response and the `PUT
/resource_providers/{uuid}/aggregates` request and response to be
identical, and to include the ``resource_provider_generation``. As with
other generation-aware APIs, if the ``resource_provider_generation``
specified in the `PUT` request does not match the generation known by
the server, a 409 Conflict error is returned.
Change-Id: I86416e35da1798cdf039b42c9ed7629f0f9c75fc
blueprint: placement-aggregate-generation
Introduce placement microversion 1.18 with a new ?required=<trait list>
query parameter accepted on the GET /resource_providers API. Results
are filtered by providers possessing *all* of the specified traits.
Empty/invalid traits result in 400 errors.
Change-Id: I8191c9a390cb02b2a38a3f1c6e29457435994981
blueprint: traits-on-list-resource-providers
This patch add new query parameter `required` to the
`GET /allocation_candidates` API, which is used to filter candidates
with required traits. The candidate attached traits return in the
provider summary also. Those API changes are added by new microversion.
Also using specific exception TraitNotFound instead of the generic
exception ValueError when invalid traits in the request.
Change-Id: Id821b5b2768dcc698695ba6570c6201e1e9a8233
Implement blueprint add-trait-support-in-allocation-candidates
This adds a limit query parameter to GET
/allocation_candidates?limit=5&resource=VCPU:1
A 'limit' filter is added to the AllocationCandidates. If set, after
the database query has been run to create the allocation requests and
provider summaries, a slice or sample of the allocation requests is
taken to limit the results. The summaries are then filtered to only
include those in the allocation requests.
This method avoids needing to make changes to the generated SQL, the
creation of which is fairly complex, or the database tables. The amount
of data queried is still high in the extreme case, but the amount of
data sent over the wire (as JSON) is shrunk. This is a trade-off that
was discussed in the spec and the discussion surrounding its review.
If it turns out that memory use server-side is an issue we can
investigate changing the SQL.
A configuration setting, [placement]/randomize_allocation_candidates,
is added to allow deployers to declare whether they want the results
to be returned in whatever order the database chooses or a random
order. The default is "False" which is expected to preserve existing
behavior and impose a packing placement strategy.
When the config setting is combined with the limit parameter, if
"True" the limited results are a random sampling from the full
results. If "False", it is a slice from the front.
This is done as a new microversion, 1.16, with updates to docs, a reno
and adjustments to the api history doc.
Change-Id: I5f3d4f49c34fd3cd6b9d2e12b3c3c4cdcb409bec
Implements: bp allocation-candidates-limit
In relevant requests to the placement API add last-modified
and cache-control headers.
According the HTTP 1.1 RFC headers last-modified headers SHOULD always
be sent and should have a tie to the real last modified time. If we do
send them, we need Cache-Control headers to prevent inadvertent caching
of resources.
This change adds a microversion 1.15 which adds the headers to GET
requests and some PUT or POST requests.
Despite what it says 'no-cache' means "check to see if the version you
have is still valid as far as the server is concerned". Since our server
doesn't currently validate conditional requests and will always return an
entity, it ends up meaning "don't cache" (which is what we want).
The main steps in the patch are:
* To both the get single entity and get collection handlers add
response.cache_control = 'no-cache'
* For single entity add response.last_modified = obj.updated_at or
obj.created_at
* For collections, discover the max modified time when traversing the
list of objects to create the serialized JSON output. In most of
those loops an optimization is done where we only check for
last-modified information if we have a high enough microversion such
that the information will be used. This is not done when listing
inventories because the expectation is that no single resource
provider will ever have a huge number of inventory records.
* Both of the prior steps are assisted by a new util method:
pick_last_modfied.
Where a time cannot be determined the current time is used.
In typical placement framework fashion this has been done in a very
explicit way, as it makes what the handler is doing very visible, even
though it results in a bit of boilerplate.
For those requests that are created from multiple objects or by doing
calculations, such as usages and aggregate associations, the current time
is used.
The handler for PUT /traits is modified a bit more extensively than some
of the others: This is because the method can either create or validate
the existence of the trait. In the case where the trait already exists,
we need to get it from the DB to get its created_at time. We only do
this if the microversion is high enough (at least 1.15) to warrant
needing the info.
Because these changes add new headers (even though they don't do
anything) a new microversion, 1.15, is added.
Partial-Bug: #1632852
Partially-Implements: bp placement-cache-headers
Change-Id: I727d4c77aaa31f0ef31c8af22c2d46cad8ab8b8e
Adds a new microversion (1.14) to the placement REST API for supporting
nested resource providers.
For POST /resource_providers and PUT /resource_providers/{uuid}, a new
optional 'parent_provider_uuid' field is added to the request payload.
For GET /resource_providers/{uuid} responses, the
'parent_provider_uuid' field and a convenience field called
'root_provider_uuid' are provided.
For GET /resource_providers, a new '?in_tree=<rp_uuid>' parameter is
supported. This parameter accepts a UUID of a resource provider. This
will cause the resulting list of resource providers to be only the
providers within the same "provider tree" as the provider identified by
<rp_uuid>
Clients for the placement REST API can specify either
'OpenStack-API-Version: placement 1.14' or 'placement latest' to handle
the new 'parent_provider_uuid' attribute and to query for resource
providers in a provider tree.
Change-Id: I4db74e4dc682bc03df6ec94cd1c3a5f5dc927a7b
blueprint: nested-resource-providers
APIImpact
This provides microversion 1.13 of the placement API, giving the
ability to POST to /allocations to set (or clear) allocations for
more than one consumer uuid.
It builds on the recent work to support a dict-based JSON format
when doing a PUT to /allocations/{consumer_uuid}.
Being able to set allocations for multiple consumers in one request
helps to address race conditions when cleaning up allocations during
move operations in nova.
Clearing allocations is done by setting the 'allocations' key for a
specific consumer to an empty dict.
Updates to placement-api-ref, rest version history and a reno are
included.
Change-Id: I239f33841bb9fcd92b406f979674ae8c5f8d57e3
Implements: bp post-allocations
In a new microversion, 1.12, include project_id and user_id in the
output of GET /allocations/{consumer_uuid} and add JSON schema
to enable PUT to /allocations/{consumer_uuid} using the same dict-based
format for request body that is used in the GET response. In later
commits a similar format will be used in POST /allocations. This
symmetry is general good form and also will make client code a little
easier.
Since GET /allocation_candiates includes objects which are capable
of being PUT to /allocations/{consumer_uuid}, its response body has
been updated as well, to change the 'allocation_requests' object
to use the dict-based format.
Internally to handlers/allocation.py the same method (_set_allocations)
is used for every microversion. Any previous data structure is
transformed into the dict-ish form. This means that pre-existing tests
(like allocation-bad-class.yaml) continue to exercise the problems it
was made for, but needs to be pinned to an older microversion, rather than
being latest.
Info about these changes is added to placement-api-ref,
rest_api_version_history and a reno.
Change-Id: I49f5680c15413bce27f2abba68b699f3ea95dcdc
Implements: bp symmetric-allocations
Closes-Bug: #1708204
/resource_providers/{rp_uuid}/allocations has been available since
microversion 1.0 [1], but wasn't listed in the "links" section of the
GET /resource_providers response. This change adds the link in a new
microversion, 1.11
[1] https://review.openstack.org/#/c/366789/
Closes-Bug: #1714275
Change-Id: I6a1d320ce914926791d5f45e89bf4c601a6b10a0
A new 1.10 API microversion is added to return information that the
scheduler can use to select a particular set of resource providers to
claim resources for an instance.
The GET /allocation_candidates endpoint takes a "resources" querystring
parameter similar to the GET /resource_providers endpoint and returns a
dict with two top-level elements:
"allocation_requests" is a list of JSON objects that contain a
serialized HTTP body that the scheduler may subsequently use in a call
to PUT /allocations/{consumer_uuid} to claim resources against a
related set of resource providers.
"provider_summaries" is a JSON object, keyed by resource provider UUID,
of JSON objects of inventory/capacity information that the scheduler
can use to sort/weigh the results of the call when making its
destination host decisions.
Change-Id: I8dadb364746553d9495aa8bcffd0346ebc0b4baa
blueprint: placement-allocation-requests
This adds GET /usages as part of a new microversion 1.9 of the
placement API. Usages can be queried by project or project/user:
GET /usages?project_id=<project id>
GET /usages?project_id=<project id>&user_id=<user id>
and will be returned as a sum of usages, for example:
200 OK
Content-Type: application/json
{
"usages": {
"VCPU": 2,
"MEMORY_MB": 1024,
"DISK_GB": 50,
...
}
}
A new method UsageList.get_all_by_project_user() has been added
for usage queries.
Part of blueprint placement-project-user
Change-Id: I8b948a4dfe6a50bea053b5dcae8f039229e2e364
This adds project_id and user_id required request parameters as part of
a new microversion 1.8 of the placement API.
Two new fields, for project and user ID, have been added to the
AllocationList object, and the method AllocationList.create_all() has
been changed to ensure that records are written to the consumers,
projects, and users tables when project_id and user_id are not None.
After an upgrade, new allocations will write consumer records and
existing allocations will have corresponding consumer records written
when they are updated as part of the resource tracker periodic task for
updating available resources.
Part of blueprint placement-project-user
Co-Authored-By: Jay Pipes <jaypipes@gmail.com>
Change-Id: I3c3b0cfdd33da87160255ead51a0d9ff73667655
In a microversion 1.7 change PUT /resource_classes/{name} so that
creation and existence validation of a custom resource class can
happen in a single request and prevent the previous behavior of
being able to update a single resource class to a new name, which is
not desirable.
The previous update_resource_class is still in place to support
microversion 1.2-1.6.
The original resource-classs.yaml sets the default microversion
header to 'latest' so for those existing tests that are using the
old style of PUT, a '1.6' header has been added. New files for
version 1.6 (to add a "no 1.7 behavior here" test) and 1.7 (testing
the new PUT behavior and explicitly verifying POST to create is
still around) are added.
Change-Id: I95f62ab2cb1ab76d18fb52b93f87ed28e4e7b5f3
Implements: bp placement-put-resource-class
This patch adds support for a REST API for CRUD operations on traits.
GET /traits: Returns all resource classes.
PUT /traits/{name}: To insert a single custom trait.
GET /traits/{name}: To check if a trait name exists.
DELETE /traits/{name}: To delete the specified trait.
GET /resource_providers/{uuid}/traits: a list of traits associated
with a specific resource provider
PUT /resource_providers/{uuid}/traits: Set all the traits for a
specific resource provider
DELETE /resource_providers/{uuid}/traits: Remove any existing trait
associations for a specific resource provider
Partial implement blueprint resource-provider-traits
Change-Id: Ia027895cbb4f1c71fd9470d8f9281d2bebb6d8a2
This patch adds a new method for deleting all inventories for a
resource provider: DELETE /resource-providers/{uuid}/inventories
Return codes:
204 NoContent on success
404 NotFound if the resource provider does not exist
405 MethodNotAllowed if a microversion is specified that is before
this change (1.5)
409 Conflict if inventory in use or if some other request concurrently
updates this resource provider
Change-Id: I1ecb12c888f873e8330367c8411d5a2ef0458495
Implements: bp delete-inventories-placement-api
Change decorator for resource based actions in root
handler to wsgi_wrapper.PlacementWsgify
This is a newly introduced wrapper class around webob.dec.wsgify
to set json formatter in case of webob exceptions.
Change-Id: I847345f7f15a46930faf8793baf801beba98d368
Closes-Bug: #1635182
Now that we merged the object method for getting the list of ResourceProviders
based on a specific amount request, we need to expose that method into a REST
API call so that the scheduler client could be calling it.
Co-Authored-By: Jay Pipes <jaypipes@gmail.com>
Change-Id: Ia8b534d20c064eb3a767f95ca22814925acfaa77
Implements: blueprint resource-providers-get-by-request
In a new 1.3 microversion, the GET /resource_providers handler gains
support for a new query parameter 'member_of' which takes a value of
'in:' and a comma separated list of aggregate uuids, or a single
aggregate uuid.
The response is the list of resource providers that are associated
with any of those aggregates, or an empty list if there are none.
If in an old microversion, the query parameter is not accepted and a
400 is returned.
Change-Id: I82fc2003ce85dcadfecfea506e7d4adb47258c7a
This patch adds support for a REST API for CRUD operations on custom
resource classes:
GET /resource_classes: return all resource classes
POST /resource_classes: create a new custom resource class
PUT /resource_classes/{name}: update name of custom resource class
DELETE /resource_classes/{name}: deletes a custom resource class
GET /resource_classes/{name}: get a single resource class
Change-Id: I99e7bcfe27938e5e4d50ac3005690ac1255d4c5e
blueprint: custom-resource-classes
/resource_providers/{uuid}/aggregates
GET for a list of aggregate uuids associated with this resource
provider
PUT to set the list of aggregate uuids associated with this this
provider
The API requests map directly to set_ and get_ aggregates on the
ResourceProvider object.
This is implemented as placement API microversion 1.1. To make that
easier a raise_404_if_not_version helper method is added to the
microversion module.
The new rest_api_version_history doc is updated to reflect this
new version.
Change-Id: I514c15c7d387cf25bf7986d07baccf0e7a785f46
Partially-Implements: blueprint generic-resource-pools-ocata
If a PUT, POST or PATCH is sent without a content-type header,
webob.dec.wsgify will raise a KeyError. Avoid this by checking for
the content-type header before reaching any wsgify calls. As noted
in the TODO within this is not the most elegant solution, but
prevents an inadvertent 500 and returns a reasonable 400.
Change-Id: I6e7dffb5dc5f0cdc78a57e8df3ae9952c55163ae
Closes-Bug: #1623517
If there is an exception in the placement API application we still
need to send the openstack-api-version header in the response:
errors are versioned too. Therefore catch the exception, add to its
headers and then reraise the exception.
This was a problem identified in the review of the initial framing
of the placement API but left for a later patch. This is that later
patch.
Change-Id: Ib83acbf74907fd9dcbdd4b0a9271ad4bae1c21b1
Partially-Implements: blueprint generic-resource-pools
The placement API will initially host resource provider
information and then will grow to provide a full placement
service. Eventually it will be fully extracted from Nova.
To facilitate that extraction, this service is being developed
with few ties to existing nova.wsgi structures. Instead it
uses relatively plain WSGI apps that are:
* uses the Routes library with declarative mapping defined in
ROUTE_DECLARATIONS
* basic wsgi apps, with webob and the request class, for each handler
define as functions
* does not use a paste-ini file to compose middleware, instead code
which minimally inspects the oslo config to know how to adjust
middleware (in the initial case choosing an auth_strategy)
Many of these "features" will be demonstrated in commits that
follow this one that enable specific behaviors for resource
providers and their inventories.
In order to ensure that this change can be merged in an atomic
fashion it includes microversion support that was previously in its
own commit.
The microversion_parse library is used in a WSGI middleware
to parse incoming microversion headers and place the
determined value into the WSGI environment at the
'placement.microversion' key. Response headers are adjusted to
add the required outgoing headers as described in:
http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html
If a client requests an invalid microversion, they will receive
a 400 response. If the microversion is of a valid form but not
available, they will received a 406 response. The format of that
response is dependent on the accept header of the request. If it
is JSON, the min and max available microversions are presented.
A request to '/' will return version discovery information.
Thus far nothing else is done with the microversion information.
It is there for when we need it in the future. For now everything
is version 1.0.
The groundwork for using gabbi to test the API is in place in
nova/tests/functional/api/openstack/placement. The gabbi tests
are included in the functional target. To run just the placement
tests it is possible to run 'tox -efunctional placement'.
Change-Id: Icb9c8f7a1fa8a9eac66c2d72f4b7e4efd4e1944f
Partially-Implements: blueprint generic-resource-pools