Skip to content

Feat/per call nova microversion#8

Draft
msherman64 wants to merge 361 commits into
openstack:masterfrom
ChameleonCloud:feat/per_call_nova_microversion
Draft

Feat/per call nova microversion#8
msherman64 wants to merge 361 commits into
openstack:masterfrom
ChameleonCloud:feat/per_call_nova_microversion

Conversation

@msherman64

Copy link
Copy Markdown
Contributor

No description provided.

jakecoll and others added 30 commits December 13, 2021 21:06
Implements filter based architexture for usage enforcement. Two filters
are included initially. MaxReservationsLengthFilter allows operators
to define the maximum reservation length of a lease in seconds.
The ExternalServiceFilter sends lease values and allocation
candidates to an external HTTP service where policies can be defined.
All filters must be enabled in blazar.conf in an enforcement group.

When ending a lease, the allocations currently associated with the
lease/reservation are sent to the enforcement layers to perform
processing. This works fine when deleting a lease, but when a lease
naturally ends, that is, when the current time is > the lease's
recorded end time, the allocation lookup returns 0 results because
we have a filter on the time of the lease/reservation by default,
which starts from datetime.now. This is really not what we want
to do when explicitly filtering on a lease/reservation, so this updates
the generic query function to not apply this filtering in this case.

It turns out, it was possible for usage enforcement's on_end
hook to run multiple times if the first reservation teardown failed.
In this circumstance, the end_lease event would be IN_PROGRESS but
the reservations would be in an error state. The code only checks
if any reservation is DELETED before trying to run on_end again.

To fix this, only try to run on_end if we detected that there was
an UNDONE end_lease event; that's the only time in which we'll
actually be responsible for running this logic.

This also updates the delete logic to be a bit more consistent with
the internal way we track states. It is not enough to check dates,
because it could be that Blazar never got around to actually
starting the leases; we should be checking events. This also makes
the logic a bit easier to understand.

NOTE::
  This also fixes something which has probably been a bug for a
  very long time. The 'end' event was never set to 'DONE' when
  a lease was terminated early by the user (via a deletion.)

Change-Id: Ic106bee4fc3f5c401c4f8d8ecb1c4e735560bcc2
Co-Authored-By: Pierre Riteau <pierre@stackhpc.com>
Co-Authored-By: Jason Anderson <jasonanderson@uchicago.edu>
Implements: blueprint flexible-reservation-usage-enforcement
If a particular reservation throws an error during its tear down, the
processing of the entire lease and all other reservations halts. This
can put the system into a bad state over time. The right thing to do is
attempt to tear down each reservation, but then raise an exception at
the end of processing all events if any of them failed.

TODO: add tests.

Change-Id: I605094fb91b549e4ab285a85e6e91b17ebe9646b
Though there was DB functionality already written for this, it was
never exposed at the API layer. This prevented hosts from having
extra capabilities explicitly removed.

To remove an extra capability, specify the capability name and
set the value explicitly to `None` (when sending JSON, send `null`.)

Existing restrictions apply; it is not possible to remove a
capability in use explicitly by an active or pending reservation.

Partial-Bug: #1674524
Change-Id: Ic0a555b6f8cd23d213189c1420781dd4e6d4e848
Change-Id: Ic8503479b1efebd29218b0cee08c993f286e5027
Change-Id: I0db77caafb672325eb7bb0903ed0e177aadfc497
Blazar is throwing an exception from a handler b/c it's trying to
update a deleted event. Not quite sure how precisely this happens.

Change-Id: I6cefc32abf11a20803d50ca7442c47e923739f73
The allocation_candidates function is used on lease create and update
to get a list of allocations to send to usage enforcement. However,
in the case of physical hosts, if not enough candidates existed,
no error would be raised at this point, leading to the entire transaction
of a lease create/update failing halfway through, but critically after
already sending the information to the enforcement service, which never
gets notified that the lease failed to create/update.

Allocations should be checked _before_ sending to the enforcment service
to make sure that there are enough in the system to satisfy the request.

This updates the allocation_candidates function to do just that. It does not
update the _matching_hosts helper function, as that is used elsewhere
and is assumed to not throw an exception, letting the caller decide what
to do based on the number of host_ids it returns.

Change-Id: I41bb74e6201bf6e74b3113f7ad88037fd4dea676
Allocation candidates are supposed to be candidates which will
be directly reserved as part of a lease, not all possible candidates.
Filter the _matching_networks call down to a list of length 1, which
is the current (non-configurable) amount of networks which can be
reserved as part of a particular network reservation.

This also updates it to raise an exception if the number of
networks found was <1

Change-Id: Ia2bf660e6f5a316975ef7b9d2c33a61d71b65f78
It is often useful to have a reference to the lease when performing
plugin start/end/before_end, in fact several plugins already fetch
this information themselves. Lease will now be a keyword argument
to all the on_* plugin calls.

Change-Id: Ifd98cd7f66a8ebff86b92c567218e965f749171a
Change-Id: Ibd59b936445b5d0e86484bd3b2cbeef5e3d47fe5
Change-Id: I700630802e38c7c930d77f5d23786ad81c42f608
Blazar retrieves a context object from the trust recorded when a lease
was created and sends it as part of notification messages. However, if
the user who created the lease is deactivated or is not a member of the
project anymore, operations modifying the lease and lease events fail to
execute with an AuthorizationFailure exception.

This is because the trust object is not valid anymore due to the change
of permissions for the trustor.

This patch removes the context from all notification messages and stops
using trusts except for the initial lease creation. This allows project
members and OpenStack admins to manage the lease after the creator user
is disabled or has been removed from the project, as well as lease
events to run properly.

Change-Id: I895e9a54948ff5fd4dbfdad71c64631d71ef98fb
Closes-Bug: #1712381
Blueprint: blazar-preemptible-instances
Change-Id: Ic5fa07c4b1fffc763302b07e8a5f6fe0e15e019e
Change-Id: I039a899b94bdaacbd460aca633c3acfbe259e571
Change-Id: I454d30af37de004e2893dc5fe2c8555c44a98943
Change-Id: Ia32cf44a6a85dcf9dfa0909baab61821ffa35579
- add initial DB models for device resource type and associated entities (custom fields, allocations)
- add api endpoints
- add device reservation lifecycle functions
Change-Id: I4b8d7e517353cd49eb34e1baa0ce4d4ec70b93cc
Change-Id: I3155d6f41970aee2ebfc94dde85ac6171e4182a4
This should only try to sync RPs for devices that Blazar is managing.

Change-Id: Ifdc08ddeb22f9c09edc7ba3a1179dec0aade7181
when lease ends, device is not cleaned up properly.
* Add authorized_projects check when matching devices

* Update tests

* Verify structure of authorized_projects field, remove extra DB query

* Add test for is_project_allowed
If a device lease fails to start, the reservation trait is never
added to the parent resource provider. If that lease is deleted,
deleting the trait fails because it does not exist. This case
will be handled by logging a message rather than failing.
when lease terminates (not deleted by user), there is no rpc call
with authentication context. therefore, enforcement on_end fails
with error "service identity not found". no enforcement filters
will be executed. this fix gets the context from the lease trust.
Change-Id: Ia2a7244ae472bb4b17f2afcaed1ea8cbfd623fec
Change-Id: I072f95bdde4ef5802b124d4595b103de8cf00b2c
This field is a list of extra information to include with allocations
so they can be used by the calendar. This should probably be configured
by the config file.
Mark-Powers and others added 29 commits March 9, 2026 13:12
Change-Id: I645c632b317893af2e8dfa7324b0d89ef5e6db91
Change-Id: I358c51a9a9d6dc5321b5bf79350da037496893a1
Change-Id: Ie33f8b45ebadfbececa3c0f867314e096243ab3e
We have added logic so that admins may bypass some restrictions
on lease creation. However, leases are created in a trust context,
and the generation of that context drops roles.

Blazar policy enforcement checks for the "admin" role to verify
admin-ness, so this means the admin exceptions don't work.

This change gets the role names from the trust, pass it through, and verify
that the "is_admin" enforcement check passes in a unit-test.

Note: create_ctx_from_trust currently looks up values from the current
request context `ctx`, the keystone session of the trust `session`, and
the session's keystone auth_ref. For consistency, we should probably
get everything except request_id and global_request_id from the auth_ref,
just in case roles, usernames, or anything else changes betwen trust creation
and the lease action being taken.
Change-Id: I4de654a544d2aa4315000805ecc30649eea9df2f
Change-Id: I1ed4ace22acd3ae088097febcca94206044b510e
unittests fail with error 'pkg_resources module
not found', because it was removed from setuptools in version 82.0.0,
and 2023.1 still relies on it. Pin setuptools<82 to ensure pkg_resources
remains available.
Tests in stestr_known_failing.txt are passing, remove it.
When a lease request filters hosts by an extra capability, e.g.
`node_type == compute_skylake`, host_get_all_by_queries did the bulk of
the work in Python. This involves running `hosts_query.all()` which auto
joins to computehost_extra_capabilities via `lazy=joined`. This caused
the DB to return the entire table of all hosts and all capabilities, no
matter what the query was.

This whole-table fetch happens once per extra capability referenced, so
it gets progressively more expensive as queries are added
(gpus>4, arch=amd64,...).

Even in the single-query case, with ~300 hosts the time to load results
from the db into python dominated, leading to 100% cpu usage at 1 req/s.

This patch moves the matching logic from python into sqlalchemy clauses,
letting the DB return only matching hosts.
Add tests for host_get_all_by_queries covering the extra-capability
logic:

- subset selection across several hosts, including that `!=` matches a
  host whose value differs but excludes a host that lacks the property
  entirely (`!=` is not the complement of `==`)
- two capability predicates ANDed together
- a capability predicate followed by a column predicate
In NovaInventory.get_servers_per_host(), blazar tries to look up whether
any nova servers are scheduled to a specific nova hypervisor. However,
nova hypervisors may be identified by hypervisor uuid, the hostname
of the compute service for that hypervisor (host), or the hostname of
the hypervisor itself (hypervisor_hostname).

For virtualized nova deployments, host==hypervisor_hostname, but for
Ironic backed hosts, many ironic nodes share a single compute service.

Nova's api for hypervisors.search with servers=true will return servers
for ALL hypervisors sharing a given compute service, rather than the
specific one queried. We have carried a patch in Nova to fall back to
matching by hypervisor_hostname as well, that is brittle.

Since this is the only place in blazar consuming this particular api
edge case, we can just do the lookup in two steps. First look up the
nova hypervisor by id or hypervisor_hostname, and then look up servers
using Nova's servers.list API, which explicitly supports filtering by
hypervisor_hostname via the `node` keyword.

If we don't need to preserve the "raise on 0 or >1 hosts found"
behavior, the call to hypervisors.search could be dropped, simplifying
the logic further.
In FakeNovaHypervisors.search(), the mock implies that Nova's
os-hypervisors search API can filter by the computehost service name,
which is incorrect. The existing tests passed because the service name
(`fake_name`) was a substring of (`fake_name.openstack.org`), and the
api does support filtering hypervisor_hostname by substring.

This removes the incorrect mocked behavior, and changes service name to
`fake_service` to disambiguate it from the hypervisor_hostname.
Adds test cases for the alembic migration tree, asserting a single
head and single base revision. Pattern is copied from Nova's
"tests/unit/db/main/test_migrations.py".

With a bad migration, we will get an output like:
`testtools.matchers._impl.MismatchError: 1 != 2: expected a single head, found: 553383923ca0, 4fe5e44880da`
on_start and on_end read the project from context.current(), but they
run in the manager's event processor, where the current context is the
service's, not the lease owner's. This works upstream because they use
trusts to impersonate the user, but the Chameleon fork removed that
mechanism in commit 5b89659, and 100be4a restored it only for
end_lease, but not on_start.

This change just reads the project from the lease, which the manager is
already passing to the event.
In the past, blazar used to use the same host ID as the nova ID. We
stopped doing this, but never updated the nova host monitor code, since
we only use ironic hosts. The ironic host handler already uses this.

Change-Id: Ic435bc0538070bebe6d357fac443bffaab56bb3b
(cherry picked from commit a862af8)
Having a pyproject.toml file means that pip
install --editable won't create .egg files. Since
2023.1 devstack doesn't support pep660, this
breaks devstack installation of our fork.

devstack supports pyproject.toml starting 2024.1
openstack/devstack@4ddd456
blazar-manager called db_api.setup_db() on every start, which runs
metadata.create_all(). This silently creates any missing tables, but
bypasses alembic_versioning. If a manager with new models starts before
`blazar-db-manage upgrade head` is run, the new tables will exist and
cause conflicts with the alembic migrations.

Alembic should already be the only thing creating and updating the db
schema, so this change shouldn't break anything. The call appears to be
left over from a long time ago, but since it only causes problem when
blazar manager "races" alembic, it could have been missed.

Starting the manager against an unmigrated database now fails with
missing-table errors instead of silently creating them.
…rvation"

This reverts commit 84fccdf.

Change-Id: Icb6dee82b955694e1e58e83e02cc0ebc2776acd0
(cherry picked from commit a587e50)
Blueprint: blazar-preemptible-instances
Change-Id: Ic5fa07c4b1fffc763302b07e8a5f6fe0e15e019e
(cherry picked from commit 9264905)
Add a backward-compatible version= param to BlazarNovaClient/NovaClientWrapper
so the flavor plugin can pin microversion 2.55 (required to set a flavor
description) without bumping the global nova_client_version.
@msherman64
msherman64 force-pushed the feat/per_call_nova_microversion branch from ea6b429 to 6d3b9d5 Compare July 24, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.