Commit Graph

29 Commits

Author SHA1 Message Date
Chris Dent 787bb33606 Use external placement in functional tests
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
2018-12-12 18:46:49 +00:00
Eric Fried 8e1ca5bf34 Use uuidsentinel from oslo.utils
oslo.utils release 3.37.0 [1] introduced uuidsentinel [2]. This change
rips out nova's uuidsentinel and replaces it with the one from
oslo.utils.

[1] https://review.openstack.org/#/c/599754/
[2] https://review.openstack.org/#/c/594179/

Change-Id: I7f5f08691ca3f73073c66c29dddb996fb2c2b266
Depends-On: https://review.openstack.org/600041
2018-09-05 09:08:54 -05:00
Zuul 392b38b6f9 Merge "Fix comments in _anchors_for_sharing_providers and related test" 2018-08-01 13:45:28 +00:00
Yikun Jiang 04afe2aae9 Fix comments in _anchors_for_sharing_providers and related test
1. Remove "GROUP by" line in _anchors_for_sharing_providers, because
this has been removed in Ib1738fb4a4664aa7b78398655fd23159a54f5f69.
2. Add reminder note when we are sure all root_provider_id values are
NOT NULL.
3. Fix note in test_anchors_for_sharing_providers, s1 get r3 only via
agg3.

trivialfix

Change-Id: Id8bfd83db58366047267ff0eeb2930a19bddbf4e
2018-08-01 16:34:50 +08:00
Zuul c90d6101f4 Merge "Remove redundant join in _anchors_for_sharing_providers" 2018-07-31 18:28:39 +00:00
Yikun Jiang 1c66a4b029 Remove redundant join in _anchors_for_sharing_providers
There is a redundant join when we want to get id from
_anchors_for_sharing_providers. The last outerjoin is used to get the
rp.UUID according rp.id, if we set get_id=True, we no longer need this
outer join.

So, we remove the redundant join in this patch.

Change-Id: Ib5fc6e4efae29dd88ce92df834700d2121ed8076
Closes-bug: #1784604
2018-07-31 18:27:39 +08:00
Chris Dent 72e4c4c8d7 [placement] Retry allocation writes server side
This change adds a fast retry loop around
AllocationList._set_allocations if a resource provider generation
conflict happens. It turns out that under high concurrency of allocation
claims being made on the same resource provider conflicts can be quite
common and client side retries are insufficient.

Because both consumer generation and resource provider generations had
raised the same exception there was no way to distinguish between the
two so a child of ConcurrentUpdateDetected has been created as
ResourceProviderConcurrentUpdateDetected. In the future this will allow
us to send different error codes to the client as well, but that change
is not done here.

When the conflict is detected, all the resource providers in the
AllocationList are reloaded and the list objects refreshed.

Logging is provided to indicate:

* at debug that a retry is going to happen
* at warning that all the retries failed and the client is going to
  see the conflict

The tests for this are a bit funky: Some mocks are used to cause the
conflicts, then the real actions after a couple of iterations.

Change-Id: Id614d609fc8f3ed2d2ff29a2b52143f53b3b1b9a
Closes-Bug: #1719933
2018-07-31 10:57:16 +01:00
Jay Pipes 11c29ae470 do not assume 1 consumer in AllocList.delete_all()
Ever since we introduced support for setting multiple consumers in a
single POST /allocations, the AllocationList.delete_all() method has
been housing a latent bad assumption and bug.

The AllocationList.delete_all() method used to assume that the
AllocationList's Allocation objects were only ever for a single
consumer, and took a shortcut in deleting the allocation by deleting all
allocations with the "first" Allocation's consumer UUID:

```python
    def delete_all(self):
        # Allocations can only have a single consumer, so take advantage of
        # that fact and do an efficient batch delete
        consumer_uuid = self.objects[0].consumer.uuid
        _delete_allocations_for_consumer(self._context, consumer_uuid)
        consumer_obj.delete_consumers_if_no_allocations(
            self._context, [consumer_uuid])
```

The problem with the above is that if you get all the allocations for a
single resource provider, using
AllocationList.get_all_by_resource_provider() and there are more than
one consumer allocating resources against that provider, then calling
AllocationList.delete_all() will only delete *some* of the resource
provider's allocations, not all of them.

Luckily, the handler code has never used AllocationList.delete_all()
after calling AllocationList.get_all_by_resource_provider(), and so
we've not hit this latent bug in production.

However, in the next patch in this series (the reshaper DB work), we
*do* call AllocationList.delete_all() for allocation lists for each
provider involved in the reshape operation, which is why this fix is
important to get done correctly.

Note that this patch renames AllocationList.create_all() to
AllocationList.replace_all() to make it absolutely clear that all of
the allocations for all consumers in the list are first *deleted* by the
codebase and then re-created. We also remove the check in
AllocationList.create_all() that the Allocation objects in the list must
not have an 'id' field set. The reason for that is because in order to
properly implement AllocationList.delete_all() to call DELETE FROM
allocations WHERE id IN (<...>) we need the list of allocation record
internal IDs. These id field values are now properly set on the
Allocation objects when AllocationList.get_all_by_resource_provider()
and AllocationList.get_all_by_consumer_id() are called. This allows that
returned object to have delete_all() called on it and the DELETE
statement to work properly.

Change-Id: I12393b033054683bcc3e6f20da14e6243b4d5577
Closes-bug: #1781430
2018-07-12 16:57:31 -04:00
Zuul 4938584f6b Merge "Ensure that os-traits sync is attempted only at start of process" 2018-06-20 18:23:02 +00:00
Chris Dent 0372d82c2c Ensure that os-traits sync is attempted only at start of process
Traits sync had been tried any time a request that might involve
traits was called. If the global was set no syncing was done, but
lock handling was happening.

This change moves the syncing into the the deploy.load_app() handling.
This means that the syncing will be attempted any time a new WSGI
application is created. Most of the time this will be at the start of a
new process, but some WSGI servers have interesting threading models so
there's a (slim) possibility that it could be in a thread. Because of
this latter possibility, the locking is still in place.

Functional tests are updated to explicitly do the sync in their
setUp(). Some changes in fixtures are required to make sure that
the database is present prior to the sync.

While these changes are not strictly part of extracting placement, the
consolidation and isolation of database handling code makes where to put
this stuff a bit cleaner and more evident: an update_database() method
in deploy uses an empty DbContext class from db_api to the call the
ensure_trait_sync method in resource_provider. update_database is in
deploy because it an app deployment task and because putting it in
db_api leads to circual import problems.

blueprint placement-extract
Closes-Bug: #1756151

Change-Id: Ic87518948ed5bf4ab79f9819cd94714e350ce265
2018-06-19 13:22:04 +01:00
Tetsuro Nakamura 562fff5208 Return all nested providers in tree
Getting allocation candidates, in provider_summaries we have only
providers that are in allocation_requests.

This patch fixes it to include all the providers in trees in play.

Change-Id: I108dceb13bdefc541b272ea953acc1dec2945647
Blueprint: placement-return-all-resources
2018-06-17 13:15:27 +09:00
Chris Dent 0044beb358 Optional separate database for placement API
If 'connection' is set in the 'placement_database' conf group use
that as the connection URL for the placement database. Otherwise if
it is None, the default, then use the entire api_database conf group
to configure a database connection.

When placement_database.connection is not None a replica of the
structure of the API database is used, using the same migrations
used for the API database.

A placement_context_manager is added and used by the OVO objects in
nova.api.openstack.placement.objects.*. If there is no separate
placement database, this is still used, but points to the API
database.

nova.test and nova.test.fixtures are adjusted to add awareness of
the placement database.

This functionality is being provided to allow deployers to choose
between establishing a new database now or requiring a migration
later. The default is migration later. A reno is added to explain
the existence of the configuration setting.

This change returns the behavior removed by the revert in commit
39fb302fd9 but done in a more
appropriate way.

Note that with the advent of the nova-status command, which checks
to see if placement is "ready" the tests here had to be adjusted.
If we do allow a separate database the code will now check the
separate database (if configured), but nothing is done with regard
to migrating from the api to placement database or checking that.

blueprint placement-extract

Change-Id: I7e1e89cd66397883453935dcf7172d977bf82e84
Implements: blueprint optional-placement-database
Co-Authored-By: Roman Podoliaka <rpodolyaka@mirantis.com>
2018-06-15 13:01:50 +01:00
Jay Pipes f449650109 placement: Allocation.consumer field
Removes the consumer_id, project_id and user_id fields from the
Allocation object definition. These values are now found in the Consumer
object that is embedded in the Allocation object which is now
non-nullable.

Modifies the serialization in the allocation handler to output
Allocation.consumer.project.external_id and
Allocation.consumer.user.external_id when appropriate for the
microversion.

Calls the create_incomplete_consumers() method during
AllocationList.get_all_by_consumer_id() and
AllocationList.get_all_by_resource_provider() to online-migrate missing
consumer records.

Change-Id: Icae5038190ab8c7bbdb38d54ae909fcbf9048912
blueprint: add-consumer-generation
2018-06-13 18:18:37 -04:00
Chris Dent ce12d7a1e5 Move db using provider unit tests to functional
Some of the ResourceProvider unit tests used the db directly.

These have been moved to the functional test_resource_provider.py and
transformed as required to make them work in that setting. Some test
cases were appended to existing tests where it made sense.

The save_immutable test which claimed to use the db, but did not,
remains in the original file but in a more suitable test class.

Change-Id: I7a91ed797b052500fdd80690cb35f1049ef6c422
2018-06-12 11:21:05 +01:00
Tetsuro Nakamura 068c56f55d Support nested alloc cands with sharing providers
This patch enables nested allocation candidates in cases where
sharing providers are also in the environment.

The logic is mainly added to the existing function
_alloc_candidates_nested_no_shared() renaming it to
_alloc_candidates_multiple_provider().

Because this new function is also available when there is neither
sharing providers nor nested providers, this patch merges the
existing _alloc_candidates_with_shared() and _get_all_with_shared()
function to _alloc_candidates_multiple_provider().

Change-Id: Ib1738fb4a4664aa7b78398655fd23159a54f5f69
Blueprint: nested-resource-providers-allocation-candidates
2018-05-29 00:02:02 +09:00
Vladyslav Drok 7f79758dd9 Placement: allow to set reserved value equal to total for inventory
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
2018-05-18 23:04:27 +00:00
Balazs Gibizer 052cefcf43 Followup for multiple member_of qparams support
* Function documentation of member_of param is fixed in multiple places
* Defaulting member_of to None instead of empty string to use a value
  that the caller documented to expect
* Fixing placement db test case that still used a single UUID list as
  member_of

Change-Id: I9b7184f8f8b1e621df61b5652956707345be2ab0
2018-05-09 14:15:01 +02:00
Eric Fried 71de700c8f Use helpers in test_resource_provider (func)
Refactor test_resource_provider to use helper methods from test_base.

Change-Id: I577751867346454e2c49dd303bb79bcb2b8f6686
2018-05-04 09:17:50 -05:00
Eric Fried e856112afa Base test module/class for functional placement db
Initial change set factoring a common base test class and helper
utilities out of test_resource_provider and test_allocation_candidates.
This one minimizes the delta by copying some module-level symbols into
the test suites.  Subsequent patches will refactor to avoid this, clean
up naming (so we're not accessing privates from another module), and use
the now-common utility methods in more places.

Change-Id: Ibd38a3903a2d347a4ff4702d0d1172f6e37e7d19
2018-05-04 08:43:20 -05:00
Zuul 0ef3c685b9 Merge "support multiple member_of qparams" 2018-05-03 18:54:21 +00:00
Jay Pipes 368b6d9293 support multiple member_of qparams
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
2018-05-03 09:02:29 -04:00
Eric Fried e2b538dd32 Get anchors for sharing providers
Individual request groups (numbered or un-numbered) in a granular
resource request may be satisfied by a sharing provider.  In such cases,
we will need to be able to figure out which non-sharing trees the
sharing provider can be associated with.

This change introduces a helper method, _anchors_for_sharing_provider,
that accepts the ID of a sharing provider and returns the UUIDs of all
the unique root providers of trees associated with the same aggregate as
the sharing provider.

The sharing provider may or may not itself be part of a tree; in either
case, its root provider UUID is included in the result.

If the sharing provider is not part of any aggregate, the empty list is
returned.

blueprint: granular-resource-requests
Co-Authored-By: Jay Pipes <jaypipes@gmail.com>

Change-Id: I2cb4e95ca15caceb8713728f17630ed97059f25e
2018-05-02 17:04:58 -05:00
Zuul 0a642e2eee Merge "Use an independent transaction for _trait_sync" 2018-04-25 02:17:35 +00:00
Zuul 17ad34ff19 Merge "Test case: traits don't sync if first access fails" 2018-04-24 15:58:22 +00:00
leizhang 7c01dd1a65 Improve check capacity sql
During a benchmark on allocation creation, I found checking allocations
capacity occupied a great amount of time when allocation table is fairly
big. Add a check on resource provider id to reduce allocation records to
be joined with resource providers and inventories.

Change-Id: Ic36809fa7161c2aa07a42669b44046993e5db058
2018-04-19 21:10:55 +08:00
Chris Dent e980f6198c [placement] Filter resource providers by forbidden traits in db
This is the db-side work for filtering resource providers by
forbidden traits. Since we control whether forbidden is allowed
or not at the API layer, we can add support here in the DB layer
such that it works all the time.

Subsequent patches will turn on the the functionality in a microversion.

Partially implements blueprint placement-forbidden-traits
Change-Id: I46796d49931df20b002d1a7e6bb3a6be34dabefa
2018-04-13 19:16:38 +01:00
Eric Fried e2924ba237 Use an independent transaction for _trait_sync
Provides a fix for the referenced bug by using an independent
transaction for the _trait_sync method, meaning it gets committed right
away regardless of what happens in the calling scope.

Change-Id: Ie9731d0df8cf52acdc7a442316a35798a4fed4cb
Closes-Bug: 1760322
2018-04-02 11:01:18 -05:00
Eric Fried 0d3d95926e Test case: traits don't sync if first access fails
Introduce a test case for the cited bug, demonstrating that, if the
first access to the traits table raises an exception, the table doesn't
get populated.

Change-Id: I345add7ea0e16a73ccf354910aff14f63b2dbbe7
Related-Bug: 1760322
2018-04-02 10:38:16 -05:00
jichen 5be3a8a415 Move placement test cases from db to placement
A set of placement functional test is in db layer and we plan to move
placement out of nova, better to move this file to
functional/api/openstack/placement

partial implement blueprint placement-extract

Change-Id: Ie25ed974a19d8fe7bc367e2e0593646a620a49e9
2018-03-22 13:27:44 +08:00