<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel><title>Nova Specs</title><link>https://specs.openstack.org/openstack/nova-specs</link><description /><language>en</language><copyright>2026, OpenStack Nova Team</copyright><item><title>Asynchronous Volume Attachments</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/async-volume-attachments.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/async-volume-attachments"&gt;https://blueprints.launchpad.net/nova/+spec/async-volume-attachments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova currently provides an attach-volume API call that blocks on multiple RPC
calls to the compute service. The reasons for these blocking calls is mostly
historical, relating to hypervisors we used to support that involve more direct
interaction with the guest and thus can predict/reserve/identify the block
device name that will be used.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In eventlet (or any greenthreading scheme), blocking requests are not as
expensive because the request handler is able to service other connections
while waiting. However, in an environment like WSGI where each request is
handled in a real thread or process, blocking requests are much more expensive.&lt;/p&gt;
&lt;p&gt;The attach volume API is one of those blocking APIs that currently involves
the API waiting for the reserve-block-device RPC call to complete. This
round-trip to the compute service can be slow if the compute service is busy in
general or if there’s a running action on the to-be-attaching instance, as
reserving the block device name takes an instance-wide lock.&lt;/p&gt;
&lt;p&gt;This is unfortunately somewhat pointless for the two main hypervisor drivers we
currently support (libvirt and vmware) as they are unable to predict or report
the block device that will be used in the guest anyway. As such, we are waiting
in the API, consuming a thread and connection, for information that isn’t
useful anyway.&lt;/p&gt;
&lt;p&gt;In WSGI mode (which we are trying to get users to move to in order to deprecate
and remove eventlet mode), this has been reported to be quite problematic as
slow (or multiple parallel) volume attach requests can consume all the
available request workers, thus causing a DoS type situation. Further, a
malicious user could presumably leverage this behavior to deny or degrade
service intentionally.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to be able to deploy nova-api in WSGI mode without
slow volume operations causing resource consumption issues.&lt;/p&gt;
&lt;p&gt;As an operator, I want issues with the backend storage to not cause the
nova-api service to exhaust request resources.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to introduce a new microversion in which the attach-volume
call will be asynchronous and return 202 instead of 200. We will delegate the
current attach-volume workflow to the conductor task api and cast or call based
on the microversion used. In the async case, the user can retrieve the expected
block device name the synchronous API call would have returned by retrieving it
from the instance’s volume-attachments.
Like before, the user needs to poll for completion of the attachment by waiting
for the volume’s state in Cinder to change to &lt;cite&gt;in-use&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;_attach_volume()&lt;/cite&gt; method in the current &lt;cite&gt;compute/api.py&lt;/cite&gt; will be moved to
the conductor task API, reachable over RPC. The API will make this delegating
call to conductor for the older microversion and cast for the new one,
returning the appropriate content and response code in each case.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;There is also an attach workflow for shelved_offloaded state which
must be considered. It talks to cinder, so it may be a candidate for moving
along with the main workflow, but it happens all in the API today, so it
may also make sense to just leave it.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There was an alternative approach (see &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/765097/2/specs/wallaby/approved/api-remove-device_name-from-attach_volume-response.rst"&gt;previous spec&lt;/a&gt;) proposed in the past
which redesigns more of the attach workflow and uses traits advertised in
placement to control which behavior is used. This seems overly complicated to
me, while also requiring a new microversion and RPC behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This will introduce a new microversion, making the attach-volume API
asynchronous.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The current behavior offers somewhat of a DoS opportunity, especially when the
API is running in WSGI mode. This will eliminate that possibility.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None, other than the notification is currently emitted before the API call
returns, and it will happen afterwards as part of this change. Since the user
making the attach call is normally not a consumer of notifications, this is not
likely to be noticed or cause any problems.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;End users who currently rely on the attach-volume API to return the expected
device name in the guest will have to retrieve that information separately from
the os-volume_attachments API. This might require polling or waiting for the
volume-attachment to complete, because the information will not be immediately
available after the attach-volume API call finishes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This work is being done to address a performance impact of exhausting resources
when in WSGI mode. This work will address that, but also generally improve
performance as async operations require fewer resources for the duration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;One benefit of this approach is that the compute service and RPC API need not
change.  Thus, the conductor being upgraded alongside the API which uses the
new task API (already required in lockstep) means that older computes will not
perceive any change if the new API is used before the upgrade is complete.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jkulik&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;This work is related to the eventlet deprecation effort, and thus should be
considered a parallel effort to address issues that are being created by
changing the only available deployment model we allow.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Move the &lt;cite&gt;_attach_volume()&lt;/cite&gt; method to the task API where it can be called&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new cast/call RPC interface for the conductor task API to perform the
attach workflow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new microversion to the API which controls whether the attach workflow
is asynchronous or not&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tempest coverage for the new microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;No direct dependencies for this work, although it may have some impact or
relation to the eventlet deprecation effort.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Typical functional and unit tests should be sufficient for this work. Existing
tempest tests for volume attachment should be trivially updatable to call the
new microversion, validate the return code, and poll for completion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The typical api-ref documentation should be sufficient for this work, as well
as a release note as this is likely of interest to operators currently
suffering from resource exhaustion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.1 G&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>Search flavors by name</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/flavor-search-by-name.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/flavor-search-by-name"&gt;https://blueprints.launchpad.net/nova/+spec/flavor-search-by-name&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow users to search for flavor by name server-side.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, there is no mechanism to filter flavors by flavor name using the
API. Instead, you must retrieve all flavors and filter manually. This can be
expensive, particularly when “flavor explosion” is taken into account. We would
like to resolve this by adding support for a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; filter.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a developer of client tooling, I would like to do as much filtering
server-side as possible, in order to improve performance and reduce
unnecessary network traffic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt; API to add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; query string
filter parameter. This will support regex-style syntax, similar to many other
existing APIs such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;. As with those APIs, this will default
to partial matches and a regular expression must be used to get exact matches.
For example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;openstack&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openstack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'devstack'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/flavors'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'/flavors'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'flavors'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="go"&gt;['m1.small', 'ci.m1.small', 'm1.medium', 'ci.m1.medium', 'm2.small', 'ds512M', 'ds1G']&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'/flavors?name=m1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'flavors'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="go"&gt;['m1.small', 'ci.m1.small', 'm1.medium', 'ci.m1.medium']&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'/flavors?name=^m1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'flavors'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="go"&gt;['m1.small', 'm1.medium']&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will be implemented by reusing the logic currently used for instances in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_regex_instance_filter&lt;/span&gt;&lt;/code&gt;, seen &lt;a class="reference external" href="https://github.com/openstack/nova/blob/41773f8c6515021eb037e6d9d385b34e89191c8c/nova/db/main/api.py#L1999-L2028"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While we are introducing a new microversion, we will also take the opportunity
to address some other tech debt with the schema:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We will set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; for the flavor show (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/flavors/{flavor_id}&lt;/span&gt;&lt;/code&gt;) API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; field from the flavor create (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;
&lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt;), flavor list with details (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/detail&lt;/span&gt;&lt;/code&gt;) and flavor
show (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/{flavor_id}&lt;/span&gt;&lt;/code&gt;) APIs. We will also remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt;
from the list of valid sort keys for the flavor list (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt;) and
flavor list with details (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/detail&lt;/span&gt;&lt;/code&gt;) APIs. This field was only
supported by the long since removed XenAPI driver and is a no-op in modern
Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-FLV-DISABLED:disabled&lt;/span&gt;&lt;/code&gt; field from the flavor list
with details (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/detail&lt;/span&gt;&lt;/code&gt;) and flavor show (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/flavors/{flavor_id}&lt;/span&gt;&lt;/code&gt;) APIs. There has never been a way to set this field,
making it a no-op.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, we will build on one of the above items and address some tech debt
with other schemas:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We will set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; for all query string
schemas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will restrict all action bodies to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;null&lt;/span&gt;&lt;/code&gt; values except those where a
value is actually expected.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We currently have to do this stuff client-side, which is less performant. We
could continue to do so.&lt;/p&gt;
&lt;p&gt;Rather than supporting a regex syntax, we could opt for a simple partial match
filter, implemented using the SQL &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LIKE&lt;/span&gt;&lt;/code&gt; operator. This is currently used for
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname_pattern&lt;/span&gt;&lt;/code&gt; filter of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-hypervisors&lt;/span&gt;&lt;/code&gt; API
(ultimately by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_node_search_by_hypervisor&lt;/span&gt;&lt;/code&gt; DB API). This would be
slightly more performant, but it would be less expressive and would result in a
potentially surprising difference in behavior compared to most other APIs.&lt;/p&gt;
&lt;p&gt;Regex support varies between our officially supported database backends,
MySQL/MariaDB and PostgreSQL, resulting in potential API behavioral differences
across deployments. We could investigate a subset of regex support that is
common across these backends and opt to support only this subset of patterns.
However, this is likely to be an involved, potentially complicated task that
would yield minimal benefit, given the &lt;a class="reference external" href="https://opendev.org/openstack/governance/commit/7999c374a391b6c702b9baafc6282649653e75a0"&gt;long-standing bias towards MySQL in
production deployments&lt;/a&gt; and absence of perceived issues with other APIs that
already suffer from this issue. Deferring to the backend’s regex support is
“good enough”.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavors&lt;/span&gt;&lt;/code&gt; model already has a &lt;a class="reference external" href="https://github.com/openstack/nova/blob/64ca204c9cf497b0dcfff2d3a24b0dd795a57d1d/nova/db/api/models.py#L231"&gt;unique
constraint&lt;/a&gt; and is therefore indexed. In addition, we do not plan to remove
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; field from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavor&lt;/span&gt;&lt;/code&gt; o.v.o. We may wish to remove the
field from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavors&lt;/span&gt;&lt;/code&gt; model but that should likely be done in a future
release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt; API will be modified to add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt;
query string filter parameter in requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt; API will be modified to remove support for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; parameter in requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All flavors API will be modified to remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-FLV-DISABLED:disabled&lt;/span&gt;&lt;/code&gt; fields from responses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All API that currently accept an unrestricted set of query string parameters
will be modified to restrict these.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All action APIs that currently restrict an unrestricted value in request
bodies will be modified to only accept &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;null&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;openstackclient and third-party clients can take advantage of this when
filtering flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None. Clients will be faster since they can take advantage of server-side
filtering, but there should be no impact on the server itself since the field
is indexed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend API and rework schemas as described above&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We will provide new unit and functional tests, including API sample tests.&lt;/p&gt;
&lt;p&gt;We will extend the Compute API schemas used in Tempest to reflect these
changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update API ref.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>libvirt - Use built-in firmware auto-selection for UEFI firmware</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/libvirt-firmware-auto-selection.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-firmware-auto-selection"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-firmware-auto-selection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Libvirt introduced its built-in firmware auto-selection for UEFI firmware,
which automatically fills paths for CODE file and VAR file of UEFI firmware
files, according to the requested features. This feature is more sophisticated
and is capable to detect a few new flags recently introduced, like AMD SEV or
stateless firmware.&lt;/p&gt;
&lt;p&gt;This spec proposes replacing the existing own logic within nova by the built-in
one, so that we don’t have to maintain our own logic and leverage the improved
mechanism in underlying libvirt.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Recent libvirt is capable to select the appropriate firmware files for domains
using UEFI boot, according to the requested features such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;secure boot&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amd-sev/amd-sev-es/amd-sev-snp&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stateless firmware&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This feature is called auto-selection in libvirt and it reads the flags
maintained in firmware descriptor files provided by qemu packages in distros.&lt;/p&gt;
&lt;p&gt;Nova introduced its own logic when secure boot support was introduced. Because
nova explicitly defines firmware files being used for every instance with
UEFI boot, libvirt skips its auto-selection feature and use the specified
files accordingly. However the existing logic in nova only considers
the secure-boot flag, so it is not able to select appropriate firmware for
the other features. As a result, an instance with additional features may be
launched with a wrong firmware file. One example is stateless firmware, for
which a firmware file with “stateless” flag should be used, but the current
nova may not consider this flag and may launch instances with a CODE file,&lt;/p&gt;
&lt;p&gt;which has non-zero VAR file associated.&lt;/p&gt;
&lt;p&gt;In addition to the new feature flags, recent QEMU packages introduced the new
ROM type firmwares. Libvirt can recognize these, but nova is not able to handle
that new types due to the different keys used to define the firmware path
file.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud administrator, I want nova to select the appropriate firmware
file according to the features user requested, without additional
configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud user, I want my instance to be booted with an appropriate
firmware, according to the feature requested.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose the following changes in the way guest XML is generated by libvirt
driver, so that firmware files are selected by libvirt according to
the requested features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stop explicitly passing paths for code file and var file when defining
a domain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Current nova fills the loader element and the nvram element when generating
a guest XML. The example below describes the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os&lt;/span&gt;&lt;/code&gt; element of a guest XML
with secure-boot.&lt;/p&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;os&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;machine=&lt;/span&gt;&lt;span class="s"&gt;'q35'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;hvm&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;loader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'pflash'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;readonly=&lt;/span&gt;&lt;span class="s"&gt;'yes'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;secure=&lt;/span&gt;&lt;span class="s"&gt;'yes'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/usr/share/OVMF/OVMF_CODE.secboot.fd&lt;span class="nt"&gt;&amp;lt;/loader&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;nvram&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;template=&lt;/span&gt;&lt;span class="s"&gt;'/usr/share/OVMF/OVMF_VARS.secboot.fd'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;boot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dev=&lt;/span&gt;&lt;span class="s"&gt;'hd'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;smbios&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;mode=&lt;/span&gt;&lt;span class="s"&gt;'sysinfo'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/os&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the proposed change is implemented, nova no longer fills these file
paths but adds the firmware feature element for secure-boot. The example
below describes the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os&lt;/span&gt;&lt;/code&gt; element of a guest XML with secure-boot.&lt;/p&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;firmware=&lt;/span&gt;&lt;span class="s"&gt;'efi'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;machine=&lt;/span&gt;&lt;span class="s"&gt;'q35'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;hvm&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;loader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;secure=&lt;/span&gt;&lt;span class="s"&gt;'yes'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;firmware&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;'yes'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'secure-boot'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/firmware&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;boot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dev=&lt;/span&gt;&lt;span class="s"&gt;'hd'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;smbios&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;mode=&lt;/span&gt;&lt;span class="s"&gt;'sysinfo'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/os&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Note that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;firmware='efi'&lt;/span&gt;&lt;/code&gt; is the key to tell libvirt detect
the firmware file paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To keep the existing behavior for guests without secure-boot, the feature
is explicitly rejected in a guest XML if secure-boot feature is not
requested.&lt;/p&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;firmware=&lt;/span&gt;&lt;span class="s"&gt;'efi'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;machine=&lt;/span&gt;&lt;span class="s"&gt;'q35'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;hvm&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;loader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;secure=&lt;/span&gt;&lt;span class="s"&gt;'no'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;firmware&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;'no'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'secure-boot'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/firmware&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;boot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dev=&lt;/span&gt;&lt;span class="s"&gt;'hd'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;smbios&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;mode=&lt;/span&gt;&lt;span class="s"&gt;'sysinfo'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/os&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, libvirt does not require these firmware feature elements for
stateless firmware (libvirt reads the stateless property in the loader
element) and AMD SEV/SEV-ES (libvirt reads the launchSecurity element).
For example, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os&lt;/span&gt;&lt;/code&gt; element of a guest XML should look like the example
below when stateless firmware is requested.&lt;/p&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;firmware=&lt;/span&gt;&lt;span class="s"&gt;'efi'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;machine=&lt;/span&gt;&lt;span class="s"&gt;'q35'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;hvm&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;loader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;secure=&lt;/span&gt;&lt;span class="s"&gt;'no'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;stateless=&lt;/span&gt;&lt;span class="s"&gt;'yes'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;firmware&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;'no'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'secure-boot'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/firmware&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;boot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dev=&lt;/span&gt;&lt;span class="s"&gt;'hd'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;smbios&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;mode=&lt;/span&gt;&lt;span class="s"&gt;'sysinfo'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/os&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;During the following operations, check the loader element and the nvram
element in the existing guest XML, and then explicitly pass these elements
and disable auto detection to generate the new guest XML, so that firmware
files are not re-selected during these operations.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;hard-reboot (and start)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;live migration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;It’s possible that the domain xml does not exist when an instance is
started (for example if the instance is booted from a volume and its host
is reinstalled). In that case xml is generated from scratch and firmware
file paths may be changed after the operation.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An alternative approach is to implement the same auto selection logic in nova,
but this requires effort to keep the implementation consistent with libvirt.
This causes concern with future code maintenance for no large benefit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Instances may be launched with a different (but correct) firmware after
the operations which generate domain XML from scratch, such as&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Start, when the domain definition does not exists on the hypervisor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebuild&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shelve&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resize or cold migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evacuate&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers have to ensure the firmware descriptor files (which are typically
located in /usr/share/qemu/firmware/) are updated to contain the flags for
the expected features.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As described in the end-user impact section, instances may be launched with
a different firmware file, when it is being launched by a new libvirt
driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After upgrade, instance creation might fail in case none of the firmware
descriptor files do not contain the required flags (sev flags and stateless
flag) which were not checked earlier.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kajinamit (irc: tkajinam)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add detection of used firmware files from existing libvirt XML&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update generation of XML file by libvirt driver to fill firmware file
paths only when these are explicitly given.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update live migration and hard reboot to pass the firmware files currently
used, when generating a new XML file.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unit tests and functional tests should be added according to new logic.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Libvirt &amp;gt;= 5.2.0 is required to use auto-selection feature. This is already
enforced by minimum libvirt version check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU firmware files and their descriptor files are updated to contain flags
for the features requested by nova. The firmware descriptor files installed
by supported distributions mostly contain the required flags, but Ubuntu
24.04 is known to require an update for AMD SEV-ES support. See &lt;a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/edk2/+bug/2122286"&gt;Bug 2122286&lt;/a&gt; for details.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Corresponding unit/functional tests will need to be extended or added
to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Simplified XML file passed during instance XML generation, which does not
contain explicit firmware file paths&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;XML file generated by hard-reboot or live migration should contain explicit
firmware file paths, according to the ones in the existing domain XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For secure boot and stateless firmware, new scenario tests may be added to
tempest. However cirros, which is currently used in CI for guest OS, does not
support UEFI boot and we need a different (and likely more heavy) guest OS for
these features. In case it was determined that we can’t use these guest in CI,
these features may be tested locally.&lt;/p&gt;
&lt;p&gt;Also, AMD SEV and AMD SEV-ES have no real firmware available in CI so these
will be manually tested.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/kbase/secureboot.html#quick-configuration"&gt;Configuration guide of UEFI boot&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.1 Gazpacho&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>Graceful Shutdown of Nova Services: Part1</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/nova-services-graceful-shutdown-part1.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-services-graceful-shutdown-part1"&gt;https://blueprints.launchpad.net/nova/+spec/nova-services-graceful-shutdown-part1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This proposes the spec 1 of the graceful shutdown &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/backlog/approved/nova-services-graceful-shutdown.html"&gt;backlog spec&lt;/a&gt; for the
2026.1 cycle.&lt;/p&gt;
&lt;p&gt;Nova services do not shut down gracefully. When services are stopped, it also
stops all the in-progress operations, which not only interrupt the in-progress
operations, but can leave instances in an unwanted or unrecoverable state. The
idea is to let services stop processing the new request, but complete the
in-progress operations before service is terminated.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova services do not have a way to shutdown gracefully means they do not wait
for the in-progress operations to be completed. When shutdown is initiated,
services wait for the RPC server to stop and wait so that they can consume all
the existing request messages (RPC call/cast) from the queue, but the service
does not complete the operation.&lt;/p&gt;
&lt;p&gt;Each Nova compute service has a single worker running and listening on a single
RPC server (topic: compute.&amp;lt;host&amp;gt;). The same RPC server is used for the new
requests as well as for in-progress operations where other compute or conductor
services communicate. When shutdown is initiated, the RPC server is stopped
means it will stop handling the new request, which is ok, but at the same
time it will stop the communication needed for the in-progress operations. For
example, if live migration is in progress, the source and destination compute
communicate (sync and async way) multiple times with each other. Once the RPC
server on the compute service is stopped, it cannot communicate with the other
compute and fails the live migration. It will lead the system as well as the
instance to be in an unwanted or unrecoverable state&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to be able to gracefully shut down (SIGTERM) the Nova
services so that it will not impact the users’ in-progress operations or
keep resources in usable state.&lt;/p&gt;
&lt;p&gt;As an operator, I want to be able to keep instances and other resources in a
usable state even if service is gracefully terminated (SIGTERM).&lt;/p&gt;
&lt;p&gt;As an operator, I want to be able to take the actual benefits of the k8s pod
graceful shutdown when Nova services are running in k8s pods.&lt;/p&gt;
&lt;p&gt;As a user, I want in-progress operations to be completed before the service
is gracefully terminated (SIGTERM).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;For detailed context, refer to the graceful shutdown &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/backlog/approved/nova-services-graceful-shutdown.html"&gt;backlog spec&lt;/a&gt;.&lt;/p&gt;
&lt;section id="split-the-new-and-in-progress-requests-via-rpc"&gt;
&lt;h3&gt;Split the new and in-progress requests via RPC:&lt;/h3&gt;
&lt;p&gt;RPC communication is an important part of services to finish a particular
operation. During shutdown, we need to make sure we keep the required RPC
servers/buses up. If we stop the RPC communication, then it is nothing
different than service termination.&lt;/p&gt;
&lt;p&gt;Nova implements, and this spec talks a lot about RPC server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;start&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stop&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wait&lt;/span&gt;&lt;/code&gt;, so let’s cover them briefly from oslo.messaging/RPC
resources point of view, and to understand this proposal in an easy way.
Most of you might know this, so you can skip this section.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;RPC server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;creation and start():&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will create the required resources on oslo.messaging side, for
example, dispatcher, consumer, listener, and queues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will handle the binding to the required exchanges.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop():&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will disable the listener ability to pick up any new message
from the queue, but will dispatch the already picked message to
the dispatcher.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will delete the consumer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will not delete the queues and exchange on the message broker side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will not stop RPC clients sending new messages to the queue, however,
they will not be picked because the consumer and listener are stopped.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;wait():&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will wait for the thread pool to finish dispatching all the already
picked messages. Basically, this will make sure methods are called on the
manager.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Analysis per services and the required proposed RPC design change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The services listed below communicate with other Nova services’ RPC servers.
Since they do not have their own RPC server, no change needed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova metadata API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-novncproxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-serialproxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-spicehtml5proxy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova scheduler: No RPC change needed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Requests handling:
Nova scheduler service runs as multiple workers, each having its own RPC
server, but all the Nova scheduler workers will listen to the same RPC
topic and queue &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler&lt;/span&gt;&lt;/code&gt; with fanout way.&lt;/p&gt;
&lt;p&gt;Currently, nova.service.py-&amp;gt;stop() calls stop() and wait() on RPC server.
Once RPC server is stopped, it will stop listening to any new messages.
But it will not impact anything on the other scheduler workers, and they
continue listening to the same queue and process the request. If any of
the scheduler worker is stopped, then the other workers will process the
request.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response handling:
Whenever there is a RPC call, oslo.messaging creates another reply queue
connected with the unique message id. This reply queue will be used to
send the RPC call response to the caller. Even if the RPC server is stopped
on this worker, it will not impact the reply queue.&lt;/p&gt;
&lt;p&gt;We still need to keep the worker up until all the responses are sent via
the reply queue, and for that, we need to implement the in-progress task
tracking in scheduler services, but that will be handled in step 2.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way, stopping a Nova scheduler worker will not impact the RPC
communication on the scheduler service.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova conductor: No RPC change needed.&lt;/p&gt;
&lt;p&gt;The Nova conductor binary is a stateless service that can spawn multiple
worker threads. Each instance of the Nova conductor has its own RPC server,
but all the Nova conductor instances will listen to  the same RPC topic
and queue &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;conductor&lt;/span&gt;&lt;/code&gt;. This allows the conductor instance to act as a
distributed worker pool such that stopping an individual conductor instance
will not impact the RPC communication for the pool of conductor instances,
allowing other available workers to process the request. Each cell has its
own pool of conductors meaning as long as one conductor is up for any given
cell the RPC communication will continue to function even when one or more
conductors are stopped.&lt;/p&gt;
&lt;p&gt;The request and response handling is done in the same way as mentioned for
the scheduler.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec does not cover the conductor single worker case. That might
requires the RPC designing for conductor as well but it need more
investigation.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova compute: RPC design change needed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request handling:
The Nova compute runs as a single worker per host, and each compute per
host has their own RPC server, listener, and separate queues. It handles
the new request as well as the communication needed for in-progress
operations on the same RPC server. To achieve the graceful shutdown, we
need to separate communication for the new requests and in-progress
operations. This will be done by adding a new RPC server in the compute
service.&lt;/p&gt;
&lt;p&gt;For easy readability, we will be using a different term for each RPC
server:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘ops RPC server’: This will be used for the new RPC server, which
will be used to finish the in-progress requests and will stay up during
shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘new request RPC server’: This will be used for the current RPC server,
which is used for the new requests and will be stopped during shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘new request RPC server’ per compute:
No change in this RPC server, but it will be used for all the new requests,
so that we can stop it during shutdown and stop the new requests on the
compute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘ops RPC server’ per compute:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Each compute will have a new ‘ops RPC server’ which will listen to a new
topic &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-ops.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-ops&lt;/span&gt;&lt;/code&gt; name is used because it
is mainly for compute operations, but a better name can be used if
needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will use the same transport layer/bus and exchange that the
‘new request RPC server’ uses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will create its own dispatcher, listener, and queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both RPC server will be bound to the same endpoints (same compute
manager), so that requests coming from either server are handled by
the same compute manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This server will be mainly used for the compute-to-compute operations and
server external events. The idea is to keep this RPC server up during
shutdown so that the in-progress operations can be finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In shutdown, nova.service will wait for the compute to tell if they
finished all their tasks, so that it can stop the ‘ops RPC server’ and
finish the shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response handling:
Irrespective of request is coming from either RPC server, whenever there
is a RPC call, oslo.messaging creates another reply queue connected with
the unique message id. This reply queue will be used to send the RPC call
response to the caller. Even RPC server is stopped on this worker, it
will not impact the reply queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute service workflow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;SIGTERM signal is handled by oslo.service, it will call stop on
nova.service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova.service will stop the ‘new request RPC server’ so that no new
requests are picked by the compute. The ‘ops RPC server’ is running and
up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova.service will wait for the manager to signal once all in-progress
operations are finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once compute signal to nova.service, then it will stop the
‘ops RPC server’ and proceed with service shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC client:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The RPC client stays as a singleton class, which is created with the
topic  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt;, meaning that by default message will be
sent via ‘new request RPC server’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If any RPC cast/call wants to send a message via the ‘ops RPC server’,
they need to override the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;topic&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-ops.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt; during
client.prepare() call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the RPC client detects an old compute (based on version_cap), then it
will fall back to send the message to the ‘new request RPC server’ topic
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which RPC cast/call will be using the ‘ops RPC server’ will be decided
during implementation, so that we can have a better judgment on what all
methods are used for the operations we want to finish during shutdown.
A draft list where we can use the ‘ops RPC server’:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is draft list and can be changed during implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Migrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Live migration:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We will be using the ‘new request RPC server’ for
check_can_live_migrate_destination and
check_can_live_migrate_source methods, as this is the very initial
phase where the compute service has not started the live
migration. If shutdown is initiated before live migration request,
came then migration should be rejected.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pre_live_migration()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;live_migration()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;prep_snapshot_based_resize_at_dest()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove_volume_connection()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;post_live_migration_at_destination()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rollback_live_migration_at_destination()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;drop_move_claim_at_destination()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;resize methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cold migration methods&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server external event&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebuild instance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;validate_console_port()
This is when the console is already requested, and if port validation
request is going on, the compute should finish it before shutdown so
that users can get their requested console.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Time based waiting for services to finish the in-progress operations:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The time based waiting is a temporary solution. Later, it will be
replaced by the proper tracking of in-progress tasks.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To make the graceful shutdown less complicated, this spec proposes a
configurable time-based waiting for services to complete their operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The wait time should be less than global graceful shutdown timeout. So that
external system or oslo.service does not shut down the service before the
service wait time is over.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some specific examples of the shutdown issues which will be solved by this
proposal:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Migrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Migration operations will use the ‘ops RPC server’.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If migration is in-progress then the service shutdown will not
terminate the migration; instead will be able to wait for the migration
to complete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Later, we will make long running migration to abort but that is out of
scope from this spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance boot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instance boot operations will continue to use the
‘new request RPC server’. Otherwise, we will not be able to stop the
new requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If instance boot requests are in progress by compute services, then
shutdown will wait for compute to boot them successfully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The instance external event will be received during graceful shutdown;
therefore, an instance boot request will not be blocked for the
external event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a new instance boot request arrives after the shutdown is initiated,
then it will stay in the queue, and the compute will handle it once it
is started again.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any operations which is reached to compute will be completed before the
service is shut down.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As per testing till now (eventlet mode), it does not require any change in
oslo.messaging but we need to test it by running compute in native thread
mode (with oslo.service threading backend ).&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="graceful-shutdown-timeouts"&gt;
&lt;h3&gt;Graceful Shutdown Timeouts:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nova service timeout:&lt;/p&gt;
&lt;p&gt;We need two configurable timeouts in Nova:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Overall Shutdown Timeouts:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The oslo.service already has the timeout (&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;)
which is configurable per service and used to timeout the SIGTERM
signal handler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The oslo.service will terminate the Nova service based on
&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;, even if the Nova service graceful shutdown
is not finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Its default value is 60 seconds, which is less for Nova services. The
proposal is to override its default value to 180 sec for all the
Nova services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The operator can override this value per Nova services.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Timeout for Nova service to finish the in-progress tasks:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When shutdown is initiated, each service needs to finish its
in-progress tasks, which can take time, and we have to timeout that
before oslo.service &lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt; reached.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need this timeout because after finishing the in-progress tasks,
Nova services need to call cleanup_host() on the manager, which also
need some time to finish. If we do not have this timeout and service
takes more time to finish in-progress tasks, then oslo.service
&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt; will not let cleanup_host() to be executed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to add this configurable timeout option per the Nova services
and their default value should be lower than &lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External system timeout:&lt;/p&gt;
&lt;p&gt;Depending on how Nova services are deployed, there might be an external
system (for example, Nova running on k8s pods) timeout for graceful shutdown.
That can impact the Nova graceful shutdown, so we need to document it
clearly that if there is external system timeout, then Nova service timeout
&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt; should be set accordingly. The external
system timeout should be higher than &lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;,
otherwise external system will timeout and will interrupt the Nova graceful
shutdown.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative for the RPC redesign is to handle the two topics per RPC
server. This needs a good amount of changes in oslo.messaging framework as well
as driver implementations. The idea is to allow oslo.messaging Target to take
more than one topic (take topic as a list) and ask the driver to create
separate consumers, listeners, dispatchers, and queues for each topic. Create
each topic binding to the exchange. This also requires oslo.messaging to
provide a new way to let the RPC server unsubscribe from a particular topic
and continue listening on other topics. We also need to redesign how RPC server
stop() and wait() works for now. This is too complicated and almost
re-designing the oslo.messaging RPC concepts.&lt;/p&gt;
&lt;p&gt;One more alternative is to track and stop sending the request from Nova api or
the scheduler service, but that will not be able to stop all the new requests
(compute to compute tasks) or let in-progress things to complete.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This should provide a positive impact on end users so that the shutdown will
not stop their in-progress operations.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No impact on normal operations, but the service shutdown will take more time.
There is a configurable timeout to control the service shutdown wait time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None other than a longer shutdown process, but they can configurable an
appropriate timeout for service shutdown.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Adding a new RPC server will impact the upgrade. The old compute will not have
the new ‘ops RPC server’ listening on topic RPC_TOPIC_OPS, so we need to handle
it with RPC versioning. If the RPC client detects an old compute (based on
version_cap), then it will fall back to send the message to the original RPC
server (listening to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt;); and therefore graceful shutdown will
not work on new compute nodes until all the computes are upgraded and the RPC
version_cap is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:&lt;/p&gt;
&lt;p&gt;gmaan&lt;/p&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the ‘ops RPC server’ on the compute service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the ‘ops RPC server’ for the operations we need to finish during
shutdown, for example, compute-to-compute tasks and server external events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC versioning due to upgrade impact.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Eventlet removal for all Nova services:
We need to make sure that graceful shutdown works fine on native threading
mode, so we need to wait until all compute services are moved to the native
threading mode. That will test the oslo.service with threading backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.service threading backend needs to consider the configurable
&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We cannot write tempest tests for this because tempest will not be able to
stop the services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can try (with some heavy live migration which will takes time) some
testing in ‘post-run’ phase like it is done for evacuate tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit and functional tests will be added.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Graceful shutdown working will be documented along with other considerations,
for example, timeout or wait time considered for the graceful shutdown.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;PoC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code change: &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/967261"&gt;https://review.opendev.org/c/openstack/nova/+/967261&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PoC results: &lt;a class="reference external" href="https://docs.google.com/document/d/1wd_VSw4fBYCXgyh5qwnjvjticNa8AnghzRmRH3H8pu4/"&gt;https://docs.google.com/document/d/1wd_VSw4fBYCXgyh5qwnjvjticNa8AnghzRmRH3H8pu4/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PTG discussions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-2026.1-ptg#L860"&gt;https://etherpad.opendev.org/p/nova-2026.1-ptg#L860&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-2025.1-ptg#L413"&gt;https://etherpad.opendev.org/p/nova-2025.1-ptg#L413&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.3d37f484b24bb0415983f345582508f7#L180"&gt;https://etherpad.opendev.org/p/r.3d37f484b24bb0415983f345582508f7#L180&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.1 Gazpacho&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>OpenAPI Schemas</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/openapi.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/openapi-4"&gt;https://blueprints.launchpad.net/nova/+spec/openapi-4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to start documenting our APIs in an industry-standard,
machine-readable manner. Doing so opens up many opportunities for both
OpenStack developer and OpenStack users alike, notably the ability to both
auto-generate and auto-validate both client tooling and documentation alike. Of
the many API description languages available, OpenAPI (fka “Swagger”) appears
to be the one with both the largest developer mindshare and the one that would
be the best fit for OpenStack due to the existing tooling used in many
OpenStack services, thus we would opt to use this format.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is a continuation of a spec that was previously approved in Dalmatian
(2024.2), Epoxy (2025.1) and Flamingo (2025.2). We merged all of the
groundwork for this in Dalmatian and worked on the response bodies schemas
in Epoxy and Flamingo but did not get them completed.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The history of API description languages has been mainly a history of
half-baked ideas, unnecessary complication, and in general lots of failure.
This history has been reflected in OpenStack’s own history of attempting to
document APIs, starting with our early use of WADL through to our experiments
with Swagger 2.0 and RAML, leading to today’s use of our custom &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
project, built on reStructuredText and Sphinx.&lt;/p&gt;
&lt;p&gt;It is only in recent years that things have started to stabilise somewhat, with
the development of widely used API description languages like OpenAPI, RAML and
API Blueprint, as well as supporting SaaS tools such as Postman and Apigee.
OpenAPI in particular has seen broad adoption across multiple sectors, with
sites as varied as &lt;a class="reference external" href="https://blog.cloudflare.com/open-api-transition"&gt;CloudFlare&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/github/rest-api-description"&gt;GitHub&lt;/a&gt; providing OpenAPI schemas for
their APIs. OpenAPI has evolved significantly in recent years and now supports
a wide variety of API patterns including things like webhooks. Even more
beneficial for OpenStack, OpenAPI 3.1 is a full superset of JSON Schema meaning
we have the ability to re-use much of the validation we already have.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an end user, I would like to have access to machine-readable, fully
validated documentation for the APIs I will be interacting with.&lt;/p&gt;
&lt;p&gt;As an end user, I want statically viewable documentation hosted as part of the
existing docs site without requiring a running instance of Nova.&lt;/p&gt;
&lt;p&gt;As an SDK/client developer, I would like to be able to auto-generate bindings
and clients, promoting consistency and minimising the amount of manual work
needed to develop and maintain these.&lt;/p&gt;
&lt;p&gt;As a Nova developer, I would like to have a verified API specification that I
can use should I need to replace the web framework/libraries we use in the
event they are no longer maintained.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This effort can be broken into a number of distinct steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new decorator for removed APIs and actions&lt;/p&gt;
&lt;p&gt;We have a number of APIs and actions that no longer have backing code and
return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;(Bad&lt;/span&gt; &lt;span class="pre"&gt;Request)&lt;/span&gt;&lt;/code&gt;, respectively. We
will not add schemas for these in the initial attempt at this so we need some
mechanism to indicate this. We will add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;removed&lt;/span&gt;&lt;/code&gt; decorator that will
highlight these removed APIs and indicate the version they were removed in
and the reason for their removal. We can later use this as a heuristic in our
tests to skip schema checks for these methods.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This was completed in Dalmatian (2024.2)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing request body and query string schemas&lt;/p&gt;
&lt;p&gt;There is already good coverage of both request bodies and query string
parameters but it is not complete. A list of incomplete schemas is given at
the end of this section. The additional schemas will merely validate what is
already allowed, which will mean extensive use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"additionalProperties":&lt;/span&gt;
&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; or empty schemas. Put another way, an API that currently ignores
unexpected request body fields or query string parameters will continue to
ignore them. We may wish to make these stricter, as we did for most APIs in
microversion 2.75, but that is a separate issue that should be addressed
separately.&lt;/p&gt;
&lt;p&gt;Once these specs are added, tests will be added to ensure all non-deprecated
and non-removed API resources have appropriate schemas.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This was completed in Dalmatian (2024.2)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;
&lt;p&gt;These will be sourced from existing OpenAPI schemas, currently published
at &lt;a class="reference external" href="https://github.com/gtema/openstack-openapi"&gt;github.com/gtema/openstack-openapi&lt;/a&gt;, from &lt;a class="reference external" href="https://github.com/openstack/tempest/tree/c0da6e843a/tempest/lib/api_schema/response/compute"&gt;Tempest’s API schemas&lt;/a&gt;,
and where necessary from new schemas auto-generated from JSON response bodies
generated in tests and manually modified handle things like enum values.&lt;/p&gt;
&lt;p&gt;Once these are added, tests will be added to ensure all non-deprecated and
non-removed API resources have appropriate response body schemas. In
addition, we will add a new configuration option that will control how we do
verification at the API layer, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. This will be an
enum value with three options:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Raise a HTTP 500 (Server Error) in the event that an API returns an
“invalid” response.&lt;/p&gt;
&lt;p&gt;This will be the default in CI i.e. for our unit, functional and
integration tests. This should not be used in production. The help text
of the option will indicate this and we will set the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;advanced&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Log a warning about an “invalid” response, prompting operations to file a
bug report against Nova.&lt;/p&gt;
&lt;p&gt;This will be initial (and likely forever) default in production.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ignore&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Disable API response body validation entirely. This is an escape hatch in
case we mess up.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The development of tooling required to gather these JSON Schema schemas and
generate an OpenAPI schema will not be developed inside Nova and is
therefore not covered by this spec. Nova will merely consume the resulting
tooling for use in documentation. It is intended that the same tool will be
usable across any OpenStack project that uses the same web frameworks
(in Nova’s case, WebOb + Routes).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The impact of middleware that modifies either the request or response will
not be accounted for in this change. This is because these are configurable
and they cannot be guaranteed to exist in a given deployment. Examples
include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sizelimit&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.middlware&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_token&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;keystonemiddleware&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a different tool&lt;/p&gt;
&lt;p&gt;We could use a different tool than OpenAPI to publish our specs. In a manner
of speaking we already do this - albeit not in a machine-readable manner -
through our use of os-api-ref.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because OpenAPI is clearly the best tool for the
It is the most widely used API description language available today and
aligns well with our existing use of JSON Schema for API validation. While it
does not support OpenStack’s microversion API design pattern out-of-the-box,
previous experiments have demonstrated that it is extensible enough to add
this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain these specs out-of-tree&lt;/p&gt;
&lt;p&gt;We could use a separate repo to store and maintain specs for Nova and the
other OpenStack services.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because it prevents us testing the specs on each
commit to Nova and means work that could be spread across multiple teams is
instead focused on one small team. It will result in more bugs and a lag
between changes to the Nova API and changes to the out-of-tree specs. It will
result in duplication of effort across Nova, Tempest, and the specs projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish the spec via an API resource rather than in our docs&lt;/p&gt;
&lt;p&gt;We could publish the spec via a new, unversioned API endpoint such as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/spec&lt;/span&gt;&lt;/code&gt;. A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; request to this would return the full spec, either
statically generated at deployment time or dynamically generated (and then
cached) at runtime.&lt;/p&gt;
&lt;p&gt;This is rejected because it brings limited advantages and multiple
disadvantages. Nova’s API is designed to be backwards-compatible and
non-extensible. As such, a user with the latest version of the spec should be
able to use it to communicate with any OpenStack deployment running a version
of Nova that supports microversions. It is also expected that the “master”
version of the spec will continuously improve as things are tightened up,
documentation is improved, and bugs or mistakes are corrected. We want
consumers of the spec to see these changes immediately rather than wait for
their deployment to be updated. Finally, OpenStack’s previous forays into
discoverable APIs, such as Keystone’s use of JSONHome or Glance’s attempts to
publish resource schemas, have seen limited take-up outside of the projects
themselves. Taken together, this all suggests there is no reason or advantage
to publishing deployment-specific specs and users would be better served by
fetching the latest version of the spec from the api-ref documentation
published on docs.openstack.org (which, one should note, is itself
intentionally unversioned).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no direct REST API impact. Users will see HTTP 500 error if they
set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; and encounter an invalid response,
however, we will not encourage use of this option in production and will
instead focus on validating this ourselves in CI.&lt;/p&gt;
&lt;p&gt;We may wish to address issues that are uncovered as we add schemas, but this
work is considered secondary to this effort and can be tackled separately.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This should be very beneficial for users who are interested in developing
client and bindings for OpenStack. In particular, this should (after an initial
effort in code generation) reduce the workload of the SDK team as well as teams
outside of OpenStack that work on client tooling such as the Gophercloud team.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be a minimal impact on API performance when validation is enabled as
we will now verify both requests and responses for all API resources. Given our
existing extensive use of JSON Schema for API validation, it is expected that
this should not be a significant issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As noted previously, there will be one new config option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. Operators may see increased warnings in their logs due
to incomplete schemas, but most if not all of these issues should be ironed out
by our CI coverage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers working on the API microversions will now be encouraged to provide
JSON Schema schemas for both requests and responses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gtema&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add missing request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add decorator to validate response body schemas against response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The actual generation of an OpenAPI documentation will be achieved via a
separate tool. It is not yet determined if this tool will live inside an
existing project, such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstacksdk&lt;/span&gt;&lt;/code&gt;, or inside a
wholly new project. In any case, it is envisaged that this tool will handle
OpenStack-specific nuances like microversions that don’t map 1:1 to OpenAPI
concepts in a consistent and documented fashion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests will ensure that schemas eventually exist for request bodies, query
strings, and response bodies.&lt;/p&gt;
&lt;p&gt;Unit, functional and integration tests will all work together to ensure that
response body schemas match real responses by setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Initially there should be no impact as we will continue to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
as-is for our &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;api-ref&lt;/span&gt;&lt;/code&gt; docs. Eventually we will replace or extend this
extension to generate documentation from our OpenAPI schema.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;section id="apis-missing-schemas"&gt;
&lt;h3&gt;APIs missing schemas&lt;/h3&gt;
&lt;p&gt;These are the APIs that are currently (as of 2024-04-11, commit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;1bca24aeb&lt;/span&gt;&lt;/code&gt;)
missing API request body schemas and query string schemas.&lt;/p&gt;
&lt;p class="rubric"&gt;Missing request body schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._inject_network_info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._reset_network&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._add_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._remove_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.sync_instances&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._force_delete&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._restore&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.reserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.unreserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LockServerController._unlock&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._associate_host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_host_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_project_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController._disassociate_host_and_project&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.add&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._pause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._unpause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RemoteConsolesController.get_rdp_console&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RescueController._unrescue&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._addSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._removeSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_confirm_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_revert_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._start_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._stop_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve_offload&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._resume&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._suspend&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Missing request query string schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.capacities&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsoleAuthTokensController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorAccessController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPPoolsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.reboot&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.shutdown&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.startup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.search&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.statistics&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.uptime&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaClassSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.defaults&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerDiagnosticsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerPasswordController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerSecurityGroupController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTopologyController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerVirtualInterfaceController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SnapshotController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VersionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We should emphasise that many - but not all - of the aforementioned APIs
are either deprecated or removed. We may wish &lt;em&gt;not&lt;/em&gt; to add schemas for
these, though by doing so we will lose the ability to generate documentation
or clients for these APIs from the OpenAPI spec.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced. Missing query schema and request body schemas added.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish response body schemas.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish response body schemas.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2026.1 Gazpacho&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish response body schemas.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>Remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/remove-os-volumes-boot-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-os-volumes-boot-api"&gt;https://blueprints.launchpad.net/nova/+spec/remove-os-volumes-boot-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Remove the undocumented, unused &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API is an undocumented, likely unknown alias for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API. It serves no purpose other than to confuse users and clients,
particularly in an era of auto-generated documentation and client tooling. We
should remove it.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a developer of client tooling, I do not wish to have to either support or
special-case ignore an API that is not documented and duplicates existing
APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API and child APIs will be modified so that it returns
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;404&lt;/span&gt; &lt;span class="pre"&gt;(Not&lt;/span&gt; &lt;span class="pre"&gt;Found)&lt;/span&gt;&lt;/code&gt; for all resources starting from a new API
microversion. While the API will continue to work for older microversions, we
will mark the method with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.api.openstack.wsgi.removed&lt;/span&gt;&lt;/code&gt; decorator to
indicate that automatic client and documentation generation tooling should
ignore the API.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; for all microversions. This would be even
easier for client tooling, but historically we have only done this out of
necessity (typically because an underlying feature has been removed).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API all all child APIs will return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;404&lt;/span&gt; &lt;span class="pre"&gt;(Not&lt;/span&gt;
&lt;span class="pre"&gt;Found)&lt;/span&gt;&lt;/code&gt; starting in the new API microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None. None of openstackclient, openstacksdk, python-novaclient, or Gophercloud
currently support or use this API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove the API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We need a release note. The API is not currently documented in the api-ref so
no changes will be needed there.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>vTPM live migration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/implemented/vtpm-live-migration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/vtpm-live-migration"&gt;https://blueprints.launchpad.net/nova/+spec/vtpm-live-migration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When Nova first added vTPM support, all non-spawn operations were &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/741500"&gt;rejected&lt;/a&gt; at the API level.
Extra work was necessary to manage the vTPM state when moving an instance. This
work was eventually completed for resize and cold migration, and those
operations were &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/639934/52"&gt;unblocked&lt;/a&gt;.
The blocks on live migration, evacuation, shelving and rescue are &lt;a class="reference external" href="https://docs.openstack.org/nova/2024.2/admin/emulated-tpm.html#limitations"&gt;still in
place&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A TPM device is &lt;a class="reference external" href="https://learn.microsoft.com/en-us/windows-server/get-started/hardware-requirements"&gt;required for certain features&lt;/a&gt;
of Windows Server 2022 and 2025, notably BitLocker Drive Encryption. It’s also
required to run &lt;a class="reference external" href="https://www.microsoft.com/en-us/windows/windows-11-specifications"&gt;Windows 11 at all&lt;/a&gt;. The
inability to live migrate instances with vTPM is a major roadblock for anyone
operating Windows guests in an OpenStack cloud.&lt;/p&gt;
&lt;p&gt;Libvirt support for vTPM live migration now exists (more details in
&lt;a class="reference internal" href="#vtpm-live-migration-2026-1-problem-description"&gt;&lt;span class="std std-ref"&gt;Problem description&lt;/span&gt;&lt;/a&gt;), but Nova changes are
necessary before being able to remove the API block. This spec describes those
changes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;span id="vtpm-live-migration-2026-1-problem-description"/&gt;&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are four aspects to vTPM live migration: shared vs non-shared vTPM state
storage, Libvirt support, and secret management. There is also an adjacent
problem, that - while not related to live migration - can be resolved by the
changes necessary to support live migration: vTPM instances cannot be started
back up by Nova after a compute host reboot.&lt;/p&gt;
&lt;section id="vtpm-state-storage"&gt;
&lt;h3&gt;vTPM state storage&lt;/h3&gt;
&lt;p&gt;vTPM state storage is not the same as instance state storage and Libvirt
supports the use of local storage and shared storage such as NFS, for both.&lt;/p&gt;
&lt;p&gt;Libvirt can be told where to store the vTPM state via the &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#tpm-device"&gt;source&lt;/a&gt; XML element, which Nova
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/config.py#L1146-L1153"&gt;does not support&lt;/a&gt;.
Nova deployments use the Libvirt default vTPM state path. On both Ubuntu and
Red Hat operating systems, this path is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/libvirt/swtpm/&amp;lt;instance&lt;/span&gt;
&lt;span class="pre"&gt;UUID&amp;gt;&lt;/span&gt;&lt;/code&gt;. This path is distinct from the instance state path.&lt;/p&gt;
&lt;p&gt;Testing will generally focus on local storage and could be expanded to shared
storage like NFS in the future. Currently the Nova CI gate does not have any
jobs that are configured with NFS.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="libvirt-support"&gt;
&lt;h3&gt;Libvirt support&lt;/h3&gt;
&lt;p&gt;Though it was impossible to find Libvirt artifacts explicitly demonstrating
vTPM live migration support for non-shared vTPM state storage, as of &lt;a class="reference external" href="https://www.libvirt.org/news.html#v8-10-0-2022-12-01"&gt;version
8.10&lt;/a&gt;, vTPM live
migration with shared vTPM storage is supported, and &lt;a class="reference external" href="https://github.com/stefanberger/swtpm/issues/525#issuecomment-914542936"&gt;this comment&lt;/a&gt;
suggests that for non-shared storage, vTPM live migration has been supported
since version 7.1.0.&lt;/p&gt;
&lt;p&gt;Therefore, this spec requires Libvirt 7.1.0. Our current minimum Libvirt
version is 8.0.0 as of 2025.1 (Epoxy), so we will not need to do any minimum
version checks while implementing this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="secret-management"&gt;
&lt;h3&gt;Secret management&lt;/h3&gt;
&lt;p&gt;When creating an instance with vTPM, Nova asks a key manager - normally
Barbican - to generate a secret. Crucially, this is done with the user’s token,
and the created secret is owned by the user, with no one else - not even admin
or the Nova service user - being able to read it. Nova then &lt;a class="reference external" href="https://libvirt.org/formatsecret.html"&gt;defines the secret
in Libvirt&lt;/a&gt;, and in the instance XML
references the secret by its UUID. This tells Libvirt to encrypt the instance’s
vTPM state using the contents of that secret as the symmetric key. Nova
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/driver.py#L8077"&gt;undefines the secret&lt;/a&gt;
once the Libvirt domain spawns successfully.&lt;/p&gt;
&lt;p&gt;For vTPM live migration to work, a Libvirt secret with the same UUID and
contents needs to be defined on the destination host so that destination
Libvirt can decrypt the vTPM state. Currently, Nova has no way of doing this.
Live migration is an admin operation, and neither admin nor the Nova service
user have access to the Barbican secret (unless the admin happens to be the
owen of the instance, but that’s an edge case). The Libvirt secret cannot be
read back on the source host either, because it’s defined as &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/host.py#L1115-L1116"&gt;private&lt;/a&gt;
and is undefined once the domain spawns.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="compute-host-reboot"&gt;
&lt;h3&gt;Compute host reboot&lt;/h3&gt;
&lt;p&gt;For the exact same reasons (lack of Barbican secret access and inability to
read the Libvirt secret back from Libvirt), Nova cannot start back up vTPM
instances after a compute host reboot.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a cloud operator, I want to be able to live migrate instances with vTPM
devices, in particular Windows instances.&lt;/p&gt;
&lt;p&gt;As a cloud user, I want to keep the contents of my instance’s vTPM private.
The cloud system should only be able to decrypt it when I request it via my
user token and the system should only keep the decryption secret around for a
limited time. I as a user am willing to accept that such privacy requirements
limit some of the admin initiated lifecycle operations on my instance.&lt;/p&gt;
&lt;p&gt;As a cloud operator, I want vTPM instances on a compute host to start back up
again after a host reboot.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Because the security of the vTPM secret (either in Barbican or in Libvirt)
affects what operations can be performed on an instance, users should be able
to specify what level of security they require, and operators need to specify
what level of security they’re willing to support. There also needs to be a
default level applied to an instance if nothing is explicitly specified.&lt;/p&gt;
&lt;p&gt;Two possible security levels are proposed. They are presented in the table
below.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security&lt;/span&gt;&lt;/code&gt; values&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Mechanism&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Security implications&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Instance mobility&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Only the instance owner has access to the Barbican secret. This is
existing behavior and will be the default behavior.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is the most secure option, as even the Nova service user and root
on the compute host cannot read the secret.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance is immovable and cannot be restarted by Nova in the event
of a compute host crash or reboot.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The Libvirt secret is persistent and retrievable.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is “medium” security. API-level admins and the Nova service user do
not have access to the secret, but it can be accessed by users with
sufficient privileges on the compute host.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance can be live migrated because Nova can read the secret back
from Libvirt on the source host and send it to the destination over RPC.
Security over the wire is left as the operator’s responsibility, but TLS
or similar is assumed. The instance can also be restarted by Nova in the
event of a compute host crash or reboot for the exact same reason.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Users are able to choose what level they require on their instance by selecting
a flavor that sets the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; flavor extra spec.  If no
specific policy was indicated in the flavor extra spec, the instance will
default to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt; policy, which is the same as legacy behavior.&lt;/p&gt;
&lt;p&gt;For simplicity, if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; is not set in the flavor extra
specs, an instance with vTPM will default to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt; TPM secret security
policy.&lt;/p&gt;
&lt;p&gt;A new image property is intentionally not provided because server rebuild is
blocked in the API. If a user were to create a server with a given TPM secret
security policy via an image property, that policy would become locked-in and
unable to be changed. The user would not be able to change the image property
because they would not be able to rebuild, and they would not be able to resize
to a different TPM secret security policy because the image property and flavor
extra spec would conflict and fail with HTTP 409.&lt;/p&gt;
&lt;p&gt;Operators are able to specify what level they support by using the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]supported_tpm_secret_security&lt;/span&gt;&lt;/code&gt; config option. This is a
per compute host list option that can take the value of one or more of the
security levels from the previous table. Its default value is all three levels.
These values are exposed as driver capability traits. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; flavor extra spec is translated to a required trait
to match the driver capabilities.&lt;/p&gt;
&lt;p&gt;The behavior of an instance during live migration is defined by its persisted
embedded flavor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; extra spec. Instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt;
cannot be live migrated. For instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;, the source compute host
reads the secret from Libvirt and sends it over RPC to the destination. Because
the instance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; value translates to a required trait,
it’s guaranteed that the destination host chosen for live migration supports
whatever behavior the instance requires.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This is the only version of this spec that covers the essentials: users of new
instances can choose the security level that they require, and operators can
choose which security levels they are willing to support given the limitations
imposed by higher security levels.&lt;/p&gt;
&lt;p&gt;We could also provide an image property for selection of the TPM secret
security policy but it would be problematic because of the current inability to
rebuild instances with vTPM (it is blocked in the API). Without the ability to
rebuild a vTPM instance, any user who chose their policy via image property
would be locked in to that policy unable to change it. They would not be able
to change the image property value because they cannot rebuild and they would
also not be able to change the policy via flavor extra spec because that would
fail due to conflicting values between image property vs flavor extra spec.&lt;/p&gt;
&lt;p&gt;If we would like to support image property in the future, we could possibly do
it if we could add the ability to rebuild vTPM instances at the same time. It
is not yet known if there are any technical limitations that prevent the
possibility of implementing rebuild, but we could certainly investigate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;No new microversion. The flavor extra spec validation code is updated to allow
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The main security consequences of this spec are the implications of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; case, anyone with sufficient access to the compute host can
read vTPM secrets. While this is not great, it’s also something the user opts
in to, and the compute host are assumed to be secured by the cloud operator.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A compute service version bump is necessary.&lt;/p&gt;
&lt;p&gt;Live migration of instances with vTPM will be blocked until the minimum
service version of the deployment is the upgraded version. The cloud must be
fully upgraded.&lt;/p&gt;
&lt;p&gt;Deployers must create flavor(s) with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; extra spec
set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; in order to enable creation of instances with the respective
TPM secret security policies.&lt;/p&gt;
&lt;p&gt;Any instances without this set are pre-existing instances and for simplicity,
they will not be migrated. If a user would like to opt-in to live migration,
they can resize their pre-existing instance to a flavor that has the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; extra spec set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Automatic migration of pre-existing instances into TPM secret security
policies could be discussed and considered as future work.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;notartom, melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt, dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; flavor extra spec, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]supported_tpm_secret_security&lt;/span&gt;&lt;/code&gt; config option&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_secret_uuid&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_secret_value&lt;/span&gt;&lt;/code&gt; fields to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object to carry the data over RPC from the
source host to the destination host in the case of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; TPM secret
security policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the pre live migration and rollback code to handle secret definition
and cleanup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the resize code to handle TPM secret security policy conversions
including absence of TPM secret security policy for pre-existing instances&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bump the service version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the existing API block to only allow live migration of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;
instances once the minimum service version has reached the bumped version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a whitebox/integration test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add regular Tempest tests if possible&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Libvirt version 7.1.0. This can be enforced dynamically in code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Nova’s functional tests are extended to test the Nova logic using the Libvirt
fixture. This is particularly useful for cases that cannot be easily tested in
a real environment, like rollback.&lt;/p&gt;
&lt;p&gt;The existing &lt;a class="reference external" href="https://opendev.org/openstack/whitebox-tempest-plugin/src/commit/bee34dbb867dc3c107f1262f68a997ef7ccff55a/whitebox_tempest_plugin/api/compute/test_vtpm.py"&gt;whitebox-tempest-plugin vTPM tests&lt;/a&gt;
are extended to test live migration in a real environment with an actual
Libvirt.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Nova’s &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/emulated-tpm.html"&gt;vTPM documentation&lt;/a&gt; is updated
to remove the live migration limitation and explain the usage of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;supported_tpm_secret_security&lt;/span&gt;&lt;/code&gt; configuration option, as well as the
implications of all possible values. The expectation that vTPM state storage is
not shared and that shared vTPM state storage live migration is untested is
made explicit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Empty.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.1 Gazpacho&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Mar 2026 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.2/approved/2026.2-template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;p&gt;If this is adding a new API microversion which alters a response schema, we
will also need a corresponding change in Tempest to add the new schema under
tempest/lib/api_schema/. This is required in order for the new microversion to
be used in Tempest tests. Otherwise, new microversion requests will fail
response schema validation in Tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.2 Hibiscus&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Jan 2026 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.2/implemented/2026.2-template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;p&gt;If this is adding a new API microversion which alters a response schema, we
will also need a corresponding change in Tempest to add the new schema under
tempest/lib/api_schema/. This is required in order for the new microversion to
be used in Tempest tests. Otherwise, new microversion requests will fail
response schema validation in Tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.2 Hibiscus&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Jan 2026 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.2/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;p&gt;If this is adding a new API microversion which alters a response schema, we
will also need a corresponding change in Tempest to add the new schema under
tempest/lib/api_schema/. This is required in order for the new microversion to
be used in Tempest tests. Otherwise, new microversion requests will fail
response schema validation in Tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.2 Hibiscus&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Jan 2026 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/backlog/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;p&gt;If this is adding a new API microversion which alters a response schema, we
will also need a corresponding change in Tempest to add the new schema under
tempest/lib/api_schema/. This is required in order for the new microversion to
be used in Tempest tests. Otherwise, new microversion requests will fail
response schema validation in Tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.2 Hibiscus&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Jan 2026 00:00:00 </pubDate></item><item><title>Graceful Shutdown of Nova Services</title><link>https://specs.openstack.org/openstack/nova-specs/specs/backlog/approved/nova-services-graceful-shutdown.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-services-graceful-shutdown"&gt;https://blueprints.launchpad.net/nova/+spec/nova-services-graceful-shutdown&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is backlog spec proposing the design of graceful shutdown.&lt;/p&gt;
&lt;p&gt;Nova services do not shut down gracefully. When services are stopped, it also
stops all the in-progress operations, which not only interrupt the in-progress
operations, but can leave instances in an unwanted or unrecoverable state. The
idea is to let services stop processing the new request, but complete the
in-progress operations before service is terminated.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova services do not have a way to shutdown gracefully means they do not wait
for the in-progress operations to be completed. When shutdown is initiated,
services wait for the RPC server to stop and wait so that they can consume all
the existing request messages (RPC call/cast) from the queue, but the service
does not complete the operation.&lt;/p&gt;
&lt;p&gt;Each Nova compute service has a single worker running and listening on a single
RPC server (topic: compute.&amp;lt;host&amp;gt;). The same RPC server is used for the new
requests as well as for in-progress operations where other compute or conductor
services communicate. When shutdown is initiated, the RPC server is stopped
means it will stop handling the new request, which is ok, but at the same
time it will stop the communication needed for the in-progress operations. For
example, if live migration is in progress, the source and destination compute
communicate (sync and async way) multiple times with each other. Once the RPC
server on the compute service is stopped, it cannot communicate with the other
compute and fail the live migration. It will lead the system as well as the
instance to be in an unwanted or unrecoverable state&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to be able to gracefully shut down (SIGTERM) the Nova
services so that it will not impact the users’ in-progress operations or
keep resources in usable state.&lt;/p&gt;
&lt;p&gt;As an operator, I want to be able to keep instances and other resources in a
usable state even if service is gracefully terminated (SIGTERM).&lt;/p&gt;
&lt;p&gt;As an operator, I want to be able to take the actual benefits of the k8s pod
graceful shutdown when Nova services are running in k8s pods.&lt;/p&gt;
&lt;p&gt;As a user, I want in-progress operations to be completed before the service
is gracefully terminated (SIGTERM).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Scope: The proposed solution is to gracefully shutdown the services for
the SIGTERM signal.&lt;/p&gt;
&lt;p&gt;The graceful shutdown is based on the following design principles:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When service shutdown is initiated by SIGTERM:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Do not process any new requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New requests should not be lost. Once service is restarted, it should
process the requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow in-progress operations to reach their quickest safe termination
point, either completion or abort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proper logging of the state of in-progress operations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep instances or other resources in a usable state&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When service shutdown is completed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Proper logging of unfinished operations.
Ideally, all the in-progress operations should be completed before service
is terminated, but if graceful shutdown times out (due to a configured
timeout, adding the timeout details in later section) then there should be
a proper logging of all the unfinished operations. This will help to
recover the system or instances.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When service is started again:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start processing the new requests in the normal way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the requests were not processed due to the shutdown being initiated,
then they stay in message broker queue and there are multiple
possibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Requests might have been picked by the other worker of that service.
For example, you can run more than one Nova scheduler (or conductor)
worker. If one of the worker is shutting down, then other worker will
process the request. This is not the case for Nova compute which is
always a single worker per compute service on specific host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a service has single worker running, then request can be picked up
once service is up again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is an opportunity for the compute service to cleanup or recover
the interrupted operation on instances during init_host(). The action
taken will depends on the tasks and its status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the service is in the stopped state for a long time, based on the
RPC and message queue timeout, there is chance that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The RPC client or server will timeout the call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The message broker queue may drop messages due to timeout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The order of requests and messages can be stale.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a graceful shutdown goal, we need to do two things:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A way to stop new requests, but do not interrupt in-progress operations.
This is proposed to be done via RPC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give services enough time to finish the operations. As a first step,
this is proposed to be done via time-based wait and later with a proper
tracking mechanism.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This backlog spec proposes achieving the above goals in multiple steps. Each
step will be proposed as a separate spec for a specific release.&lt;/p&gt;
&lt;section id="the-nova-services-which-already-gracefully-shutdown"&gt;
&lt;h3&gt;The Nova services which already gracefully shutdown:&lt;/h3&gt;
&lt;p&gt;For the below services, their graceful shutdown is handled by their
deployment servers or used library.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nova API &amp;amp; Nova metadata API:&lt;/p&gt;
&lt;p&gt;Those services are deployed using a server with WSGI support. That server
will ensure that Nova API services shuts down gracefully, meaning it
finishes the in-progress requests and rejects the new requests.&lt;/p&gt;
&lt;p&gt;I investigate with uWSGI/mod_proxy_uwsgi (devstack env). On service start,
uWSGI server pre-spawn the number of workers for API service which will
handle the API requests in distributed way. When shutdown is initiated
by SIGTERM, the uWSGI server SIGTERM handler check if there are any
in-progress request on any worker. It wait for all the workers to finish
the request and then terminates each worker. Once all worker are terminated
then it will terminate the Nova API service.&lt;/p&gt;
&lt;p&gt;If any new request comes after the shutdown is initiated, it will be rejected
with “503 Service Unavailable” error.&lt;/p&gt;
&lt;p&gt;Testing:&lt;/p&gt;
&lt;p&gt;I tested two types of requests:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Sync request: ‘openstack server list’:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To observe the graceful shutdown, I added 10 seconds of sleep in the
server list API code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start a API request ‘request1’: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait till the server list request reaches the Nova API (you can see
the log from the controller)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because of sleep(10), the server list takes time to finish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initiate the Nova API service shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start a new API request ‘request2’: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt;. This new
requests came after shutdown is initiated so it should be denied.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API service will wait because ‘request1’ is not finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘request1’ will get the response of the server list before the service
is terminated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘request2’ is denied and will receive the error
“503 Service Unavailable”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Async request: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;pause&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;server&amp;gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To observe the graceful shutdown, I added 10 seconds of sleep in the
server pause API code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start a API request ‘request1’: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;pause&lt;/span&gt; &lt;span class="pre"&gt;server1&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait till the pause server request reaches the Nova API (you can see
the log from the controller)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because of sleep(10), the pause server takes time to finish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initiate the Nova API service shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service will wait because ‘request1’ is not finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API will make an RPC cast to the Nova compute service and return.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘request1’ is completed, and the response is returned to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API service is terminated now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova compute service is operating the pause server request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if server is paused &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can see the server is paused.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova console proxy services: nova-novncproxy, nova-serialproxy, and
nova-spicehtml5proxy:&lt;/p&gt;
&lt;p&gt;All the console proxy services run as &lt;a class="reference external" href="https://github.com/novnc/websockify/blob/e9bd68cbb81ab9b0c4ee5fa7a62faba824a142d1/websockify/websocketproxy.py#L300"&gt;websockify.websocketproxy&lt;/a&gt; service.
The &lt;a class="reference external" href="https://github.com/novnc/websockify"&gt;websockify&lt;/a&gt; library handles the SIGTERM signal and the graceful shutdown,
which is enough for the Nova services.&lt;/p&gt;
&lt;p&gt;When a user access the console, websockify library starts a new process
in &lt;a class="reference external" href="https://github.com/novnc/websockify/blob/e9bd68cbb81ab9b0c4ee5fa7a62faba824a142d1/websockify/websockifyserver.py#L861"&gt;start_service&lt;/a&gt; and calls Nova &lt;a class="reference external" href="https://github.com/openstack/nova/blob/23b462d77df1a1d09c43d0918bca853ef3af1e3f/nova/console/websocketproxy.py#L164C9-L164C29"&gt;new_websocket_client&lt;/a&gt; . Nova will be
authorizing the token, creating a socket on the host &amp;amp; port, which will
be used to send the data/frames. After that, user can access the console.&lt;/p&gt;
&lt;p&gt;If a shutdown request is initiated, websockify  handle the signal. First,
it will terminate all the child processes and then raise the terminate
exception, which ends up calling the Nova &lt;a class="reference external" href="https://github.com/openstack/nova/blob/23b462d77df1a1d09c43d0918bca853ef3af1e3f/nova/console/websocketproxy.py#L150"&gt;close_connection&lt;/a&gt; method. The
Nova &lt;a class="reference external" href="https://github.com/openstack/nova/blob/23b462d77df1a1d09c43d0918bca853ef3af1e3f/nova/console/websocketproxy.py#L150"&gt;close_connection&lt;/a&gt; method calls shutdown() on the socket first and
then close(), which makes sure to send the remaining data/frame before
closing the socket.&lt;/p&gt;
&lt;p&gt;This way, user console sessions will be terminated gracefully, and they will
get “Disconnected” message. Once service is up, the user can refresh the
browser, and the console will be up again (if the token has not expired).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="spec-1-split-the-new-and-in-progress-requests-via-rpc"&gt;
&lt;h3&gt;Spec 1: Split the new and in-progress requests via RPC:&lt;/h3&gt;
&lt;p&gt;RPC communication is an important part of services to finish a particular
operation. During shutdown, we need to make sure we keep the required RPC
servers/buses up. If we stop the RPC communication, then it is nothing
different than service termination.&lt;/p&gt;
&lt;p&gt;Nova implements, and this spec talks a lot about RPC server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;start&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stop&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wait&lt;/span&gt;&lt;/code&gt;, so let’s cover them briefly from oslo.messaging/RPC
resources point of view, and to understand this proposal in an easy way.
Most of you might know this, so you can skip this section.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;RPC server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;creation and start():&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will create the required resources on oslo.messaging side, for
example, dispatcher, consumer, listener, and queues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will handle the binding to the required exchanges.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop():&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will disable the listener ability to pick up any new message
from the queue, but will dispatch the already picked message to
the dispatcher.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will delete the consumer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will not delete the queues and exchange on the message broker side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will not stop RPC clients sending new messages to the queue, however,
they will not be picked because the consumer and listener are stopped.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;wait():&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will wait for the thread pool to finish dispatching all the already
picked messages. Basically, this will make sure methods are called on the
manager.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Analysis per services and the required proposed RPC design change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The services listed below communicate with other Nova services’ RPC servers.
Since they do not have their own RPC server, no change needed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova metadata API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-novncproxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-serialproxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-spicehtml5proxy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova scheduler: No RPC change needed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Requests handling:
Nova scheduler service runs as multiple workers, each having its own RPC
server, but all the Nova scheduler workers will listen to the same RPC
topic and queue &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler&lt;/span&gt;&lt;/code&gt; with fanout way.&lt;/p&gt;
&lt;p&gt;Currently, nova.service.py-&amp;gt;stop() calls stop() and wait() on RPC server.
Once RPC server is stopped, it will stop listening to any new messages.
But it will not impact anything on the other scheduler worker, and they
continue listening to the same queue and process the request. If any of
the scheduler worker is stopped, then the other workers will process the
request.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response handling:
Whenever there is a RPC call, oslo.messaging creates another reply queue
connected with the unique message id. This reply queue will be used to
send the RPC call response to the caller. Even if the RPC server is stopped
on this worker, it will not impact the reply queue.&lt;/p&gt;
&lt;p&gt;We still need to keep the worker up until all the responses are sent via
the reply queue, and for that, we need to implement the in-progress task
tracking in scheduler services, but that will be handled in step 2.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way, stopping a Nova scheduler worker will not impact the RPC
communication on the scheduler service.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova conductor: No RPC change needed.&lt;/p&gt;
&lt;p&gt;The Nova conductor binary is a stateless service that can spawn multiple
worker threads. Each instance of the Nova conductor has its own RPC server,
but all the Nova conductor instances will listen to  the same RPC topic
and queue &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;conductor&lt;/span&gt;&lt;/code&gt;. This allows the conductor instance to ack as a
distributed worker pool such that stopping an individual conductor instance
will not impact the RPC communication for the pool of conductor instances,
allowing other available workers to process the request. Each cell has its
own pool of conductors meaning as long as one conductor is up for any given
cell the RPC communication will continue to function even when one or more
conductors are stopped.&lt;/p&gt;
&lt;p&gt;The request and response handling is done in the same way as mentioned for
the scheduler.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec does not cover the conductor single worker case. That might
requires the RPC designing for conductor as well but it need more
investigation.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova compute: RPC design change needed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request handling:
The Nova compute runs as a single worker per host, and each compute per
host has their own RPC server, listener, and separate queues. It handles
the new request as well as the communication needed for in-progress
operations on the same RPC server. To achieve the graceful shutdown, we
need to separate communication for the new requests and in-progress
operations. This will be done by adding a new RPC server in the compute
service.&lt;/p&gt;
&lt;p&gt;For easy readability, we will be using a different term for each RPC
server:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘ops RPC server’: This will be used for the new RPC server, which
will be used to finish the in-progress requests and will stay up during
shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘new request RPC server’: This will be used for the current RPC server,
which is used for the new requests and will be stopped during shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘new request RPC server’ per compute:
No change in this RPC server, but it will be used for all the new requests,
so that we can stop it during shutdown and stop the new requests on the
compute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘ops RPC server’ per compute:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Each compute will have a new ‘ops RPC server’ which will listen to a new
topic &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-ops.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-ops&lt;/span&gt;&lt;/code&gt; name is used because it
is mainly for compute operations, but a better name can be used if
needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will use the same transport layer/bus and exchange that the
‘new request RPC server’ uses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will create its own dispatcher, listener, and queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both RPC server will be bound to the same endpoints (same compute
manager), so that requests coming from either server are handled by
the same compute manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This server will be mainly used for the compute-to-compute operations and
server external events. The idea is to keep this RPC server up during
shutdown so that the in-progress operations can be finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In shutdown, nova.service will wait for the compute to tell if they
finished all their tasks, so that it can stop the ‘ops RPC server’ and
finish the shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response handling:
Irrespective of request is coming from either RPC server, whenever there
is a RPC call, oslo.messaging creates another reply queue connected with
the unique message id. This reply queue will be used to send the RPC call
response to the caller. Even RPC server is stopped on this worker, it
will not impact the reply queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute service workflow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;SIGTERM signal is handled by oslo.service, it will call stop on
nova.service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova.service will stop the ‘new request RPC server’ so that no new
requests are picked by the compute. The ‘ops RPC server’ is running and
up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova.service will wait for the manager to signal once all in-progress
operations are finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once compute signal to nova.service, then it will stop the
‘ops RPC server’ and proceed with service shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Timeout:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;There is an existing &lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt; config option present
on oslo.service which can be set per service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That is honoured to timeout the service stop, and it will stop service
irrespective of the compute finishing the things.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC client:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The RPC client stays as a singleton class, which is created with the
topic  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt;, meaning that by default message will be
sent via ‘new request RPC server’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If any RPC cast/call wants to send a message via the ‘ops RPC server’,
they need to override the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;topic&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-ops.&amp;lt;host&amp;gt;&lt;/span&gt;&lt;/code&gt; during
client.prepare() call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which RPC cast/call will be using the ‘ops RPC server’ will be decided
during implementation, so that we can have a better judgment on what all
methods are used for the operations we want to finish during shutdown.
A draft list where we can use the ‘ops RPC server’:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is draft list and can be changed during implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Migrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Live migration:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We will be using the ‘new request RPC server’ for
check_can_live_migrate_destination and
check_can_live_migrate_source methods, as this is the very initial
phase where the compute service has not started the live
migration. If shutdown is initiated before live migration request,
came then migration should be rejected.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pre_live_migration()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;live_migration()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;prep_snapshot_based_resize_at_dest()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove_volume_connection()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;post_live_migration_at_destination()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rollback_live_migration_at_destination()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;drop_move_claim_at_destination()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;resize methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cold migration methods&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server external event&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebuild instance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;validate_console_port()
This is when the console is already requested, and if port validation
request is going on, the compute should finish it before shutdown so
that users can get their requested console.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Time based waiting for services to finish the in-progress operations:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The time based waiting is a temporary solution in spec 1. In spec 2,
it will be replaced by the proper tracking of in-progress tasks.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To make the graceful shutdown less complicated, spec 1 proposes to
configurable time-based waiting for services to complete their operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The wait time should be less than global graceful shutdown timeout. So that
external system or oslo.service does not shut down the service before the
service wait time is over.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will be configurable per service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proposal for the default value:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;compute service: 150 sec, considering long-running operations on compute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;conductor service: 60 sec should be enough.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;scheduler service: 60 sec should be enough.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PoC:
This PoC shows the working of the spec 1 proposal.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Code change: &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/967261"&gt;https://review.opendev.org/c/openstack/nova/+/967261&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PoC results: &lt;a class="reference external" href="https://docs.google.com/document/d/1wd_VSw4fBYCXgyh5qwnjvjticNa8AnghzRmRH3H8pu4/"&gt;https://docs.google.com/document/d/1wd_VSw4fBYCXgyh5qwnjvjticNa8AnghzRmRH3H8pu4/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some specific examples of the shutdown issues which will be solved by this
proposal:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Migrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Migration operations will use the ‘ops RPC server’.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If migration is in-progress then the service shutdown will not
terminate the migration; instead will be able to wait for the migration
to complete.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance boot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instance boot operations will continue to use the
‘new request RPC server’. Otherwise, we will not be able to stop the
new requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If instance boot requests are in progress by compute services, then
shutdown will wait for compute to boot them successfully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a new instance boot request arrives after the shutdown is initiated,
then it will stay in the queue, and the compute will handle it once it
is started again.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any operations which is reached to compute will be completed before the
service is shut down.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As per my PoC and manual testing till now, it does not require any
change on oslo.messaging side.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="spec-2-smartly-track-and-wait-for-the-in-progress-operations"&gt;
&lt;h3&gt;Spec 2: Smartly track and wait for the in-progress operations:&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The below services graceful shutdown is handled by their deployed server or
library so no work is needed for Spec 2:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova metadata API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-novncproxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-serialproxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-spicehtml5proxy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The below services need to implement the tracking system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nova compute&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova conductor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova scheduler&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This proposal is to make the service wait time based on tracking the
in-progress tasks. Once the service finishes the tasks, then they can signal
to nova.service to proceed with shutting down the service. Basically, this
replaces the wait time approach mentioned above with a tracker-based approach.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;There will be a task tracker introduced to track the in-progress tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will be a singleton object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It maintains a list of ‘method names’ and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;request-id&lt;/span&gt;&lt;/code&gt;. If task is related
to instance, then we can add the instance UUID also that can help to filter
or know what all operations on specific instance is in-progress. The unique
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;request-id&lt;/span&gt;&lt;/code&gt; will help to track multiple calls to the same method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whenever a new request comes to compute, it will add that to the task list
and remove it once the task is completed. Modification to the tracker will be
done under lock.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once shutdown is initiated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The task tracker will either add the new tasks to the tracker list or
reject them. The decision will be made by case, for example, reject the
tasks if they are not critical to handle during shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;During shutdown, any new periodic tasks will be denied, but in-progress
periodic tasks will be finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An exact list of tasks which will be rejected and accepted will be decided
during implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The task tracker will start logging the tasks which are in progress, and
log when they are completed. Basically, log the detail view of in-progress
things during shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova.service will wait for the task tracker to finish the in-progress tasks
until timeout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example of the flow of RPC servers stop, wait, and task tacker wait will be
something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We can signal tast tracker to start logging the in-progress tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPCserver1.stop()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPCserver1.wait()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;manager.finish_tasks(): wait for manager to finish the in-progress tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPCserver2.stop()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPCserver2.wait()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="spec-3-safe-termination-point-for-nova-operations"&gt;
&lt;h3&gt;Spec 3: Safe termination point for Nova Operations:&lt;/h3&gt;
&lt;p&gt;In graceful shutdown, all the in-progress operations should reach their safe
termination point, either completion or abort.&lt;/p&gt;
&lt;p&gt;This needs to be done based on the operation type and at what stage they are
in. There are some operations, for example, pre-copy live migration, cold
migration, resize, snapshot, or shelve_offload are ok to abort with proper
logging and exception type. The user can request them again once the service
is up.&lt;/p&gt;
&lt;p&gt;Some operation, for example, post-copy live migrations are difficult to
abort if VM is already moved to the destination compute. This might need
some way to revert the VM to the source or let it complete.&lt;/p&gt;
&lt;p&gt;The scope of this spec is to investigate and audit all the operations
and categorize them ‘Ok to abort’ and ‘Wait to complete’. Accordingly,
graceful shutdown needs to implement the logic to abort or continue to
wait for the operation completion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="graceful-shutdown-timeouts"&gt;
&lt;h3&gt;Graceful Shutdown Timeouts:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nova service timeout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;oslo.service already has the timeout (&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;)
which is configurable per service and used to timeout the SIGTERM signal
handler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.service will terminate the Nova service based on
&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;, even Nova service graceful shutdown is not
finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No new configurable timeout will be added for the Nova, instead it will use
the existing &lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Its default value is 60 sec, which is less for Nova services. The proposal
is to override its default value per Nova services:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;compute service: 180 sec (Considering the long running tasks).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;conductor service: 80 sec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;scheduler service: 80 sec&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External system timeout:&lt;/p&gt;
&lt;p&gt;Depending on how Nova services are deployed, there might be an external
system (for example, Nova running on k8s pods) timeout for graceful shutdown.
That can impact the Nova graceful shutdown, so we need to document it
clearly that if there is external system timeout, then Nova service timeout
&lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt; should be set accordingly. The external
system timeout should be higher than &lt;a class="reference external" href="https://github.com/openstack/oslo.service/blob/8969233a0a45dad06c445fdf4a66920bd5f3eef0/oslo_service/_options.py#L60"&gt;graceful_shutdown_timeout&lt;/a&gt;,
otherwise external system will timeout and will interrupt the Nova graceful
shutdown.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative for the RPC redesign is to handle the two topics per RPC
server. This needs a good amount of changes in oslo.messaging framework as well
as driver implementations. The idea is to allow oslo.messaging Target to take
more than one topic (take topic as a list) and ask the driver to create
separate consumers, listeners, dispatchers, and queues for each topic. Create
each topic binding to the exchange. This also requires oslo.messaging to
provide a new way to let the RPC server unsubscribe from a particular topic
and continue listening on other topics. We also need to redesign how RPC server
stop() and wait() works for now. This is too complicated and almost
re-designing the oslo.messaging RPC concepts.&lt;/p&gt;
&lt;p&gt;One more alternative is to track and stop sending the request from Nova api or
the scheduler service, but that will not be able to stop all the new requests
(compute to compute tasks) or let in-progress things to complete.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This should provide a positive impact on end users so that the shutdown will
not stop their in-progress operations.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No impact on normal operations, but the service shutdown will take more time.
There is a configurable timeout to control the service shutdown wait time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None other than a longer shutdown process, but they can configurable an
appropriate timeout for service shutdown.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Adding a new RPC server will impact the upgrade. The old compute will not have
the new ‘ops RPC server’ listening on topic RPC_TOPIC_OPS, so we need to handle
it with RPC versioning. If the RPC client detects an old compute (based on
version_cap), then it will fall back to send the message to the original RPC
server (listening to RPC_TOPIC).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:&lt;/p&gt;
&lt;p&gt;gmaan&lt;/p&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;gmaan&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the ‘ops RPC server’ on the compute service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the ‘ops RPC server’ for the operations we need to finish during
shutdown, for example, compute-to-compute tasks and server external events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC versioning due to upgrade impact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a task tracker for services to track and report the in-progress
tasks during shutdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;No dependency as of now, but we will see during implementation if any change
is needed in oslo.messaging.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We cannot write tempest tests for this because tempest will not be able to
stop the services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can try (with some heavy live migration which will takes time) some
testing in ‘post-run’ phase like it is done for evacuate tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit and functional tests will be added.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Graceful shutdown working will be documented along with other considerations,
for example, timeout or wait time considered for the graceful shutdown.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;PoC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code change: &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/967261"&gt;https://review.opendev.org/c/openstack/nova/+/967261&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PoC results: &lt;a class="reference external" href="https://docs.google.com/document/d/1wd_VSw4fBYCXgyh5qwnjvjticNa8AnghzRmRH3H8pu4/"&gt;https://docs.google.com/document/d/1wd_VSw4fBYCXgyh5qwnjvjticNa8AnghzRmRH3H8pu4/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PTG discussions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-2026.1-ptg#L860"&gt;https://etherpad.opendev.org/p/nova-2026.1-ptg#L860&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-2025.1-ptg#L413"&gt;https://etherpad.opendev.org/p/nova-2025.1-ptg#L413&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.3d37f484b24bb0415983f345582508f7#L180"&gt;https://etherpad.opendev.org/p/r.3d37f484b24bb0415983f345582508f7#L180&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.1 Gazpacho&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 03 Dec 2025 00:00:00 </pubDate></item><item><title>Support for tracking traits removed from provider.yaml</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/approved/copy-applied-provider-yaml.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/copy-applied-provider-yaml"&gt;https://blueprints.launchpad.net/nova/+spec/copy-applied-provider-yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes a feature to ensure that traits removed from the
provider.yaml are also properly deleted from the resource provider.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova-compute has a feature to register custom traits with the resource provider
using config files (provider.yaml).
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html"&gt;https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this configuration file, even if the values of custom traits are modified or
the trait is deleted, the original trait does not be removed from the target
resource provider.
In scenarios where the custom trait registered with the resource provider is
replaced and old custom traits affect scheduling, this behavior can be a
problem.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud operator, I would like to ensure that only one trait is registered
with the resource provider for custom traits of the same type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud operator, I would like to complete the registration of custom
traits in the config file of nova-compute without additional implementation
(calling the Placement API using API/CLI in another system).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose adding a process for nova-compute to copy the contents of the
provider.yaml file to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/nova/applied_provider.yaml&lt;/span&gt;&lt;/code&gt; after they have
been applied to the placement.&lt;/p&gt;
&lt;p&gt;Then, when updating the placement based on the provider.yaml file, nova-compute
perform a diff between &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/nova/applied_provider.yaml&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/etc/nova/provider.yaml&lt;/span&gt;&lt;/code&gt; to detect if any traits have been removed from the
provider.yaml file.&lt;/p&gt;
&lt;p&gt;For now, the diff is limited to traits, but later this logic can be extended to
allow the use of the diff for any part of the provider.yaml.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Register only the custom traits defined in the file with the resource
provider, treating provider.yaml as declarative data. However, this is a
destructive change and there are concerns about the impact on the existing
environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a definition like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;declarative_prefix&lt;/span&gt;&lt;/code&gt; to provider.yaml to handle only
traits with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;declarative_prefix&lt;/span&gt;&lt;/code&gt; declaratively. In this case, the
extensibility to non-trait elements in provider.yaml is limited, and both the
definition in provider.yaml and the code of the resource tracker become
complex.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No performance impact on nova is anticipated. If there are frequent updates to
custom traits, requests for deleting and creating traits will be frequently
sent to the Placement API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mkuroha&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the copying of provider.yaml and extraction of trait diffs with
applied_provider.yaml in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_merge_provider_configs&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add unit/functional tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the existing &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html"&gt;Managing Resource Providers Using Config Files&lt;/a&gt; guide
to explation the behavior with applied_provider.yaml.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2026.1 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 05 Nov 2025 00:00:00 </pubDate></item><item><title>Remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/approved/remove-os-volumes-boot-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-os-volumes-boot-api"&gt;https://blueprints.launchpad.net/nova/+spec/remove-os-volumes-boot-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Remove the undocumented, unused &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API is an undocumented, likely unknown alias for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API. It serves no purpose other than to confuse users and clients,
particularly in an era of auto-generated documentation and client tooling. We
should remove it.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a developer of client tooling, I do not wish to have to either support or
special-case ignore an API that is not documented and duplicates existing
APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API and child APIs will be modified so that it returns
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; for all resources starting from a new API microversion.
While the API will continue to work for older microversions, we will mark
the method with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.api.openstack.wsgi.removed&lt;/span&gt;&lt;/code&gt; decorator to indicate
that automatic client and documentation generation tooling should ignore the
API.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; for all microversions. This would be even
easier for client tooling, but historically we have only done this out of
necessity (typically because an underlying feature has been removed).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-volumes_boot&lt;/span&gt;&lt;/code&gt; API all all child APIs will return HTTP 410 (Gone)
starting in the new API microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None. None of openstackclient, openstacksdk, python-novaclient, or Gophercloud
currently support or use this API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove the API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We need a release note. The API is not currently documented in the api-ref so
no changes will be needed there.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Sep 2025 00:00:00 </pubDate></item><item><title>libvirt driver launching instances with memory encryption by AMD SEV-ES</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/implemented/amd-sev-es-libvirt-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/amd-sev-es-libvirt-support"&gt;https://blueprints.launchpad.net/nova/+spec/amd-sev-es-libvirt-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes work required in order to extend the existing libvirt driver
feature to launch AMD SEV-encrypted instances, to support also using AMD
SEV-ES, which is the extended version of AMD SEV, as memory encryption
mechanism.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current libvirt driver supports launching instances with memory encryption by
&lt;a class="reference external" href="https://developer.amd.com/sev/"&gt;AMD’s SEV (Secure Encrypted Virtualization) technology&lt;/a&gt;. However the current implementation supports
only AMD SEV, and does not support new versions. For exmaple SEV-ES also
encrypts all CPU register contents when a VM stops running, to achieve more
complete protection of VM data, but users can’t leverage these features because
of this limitation.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;At the time or writing AMD already released CPUs which supports SEV-SNP, but
the required hypervisor features to use SEV-SNP are not yet merged into
the underlying components(kernel, QEMU, libvirt and ovmf). So in this spec
we focus on SEV-ES. We attempt to keep the proposal as much compatible with
SEV-SNP as possible, based on the implementations published by AMD.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud administrator, in order that my users can have more confidence
in the security of their running instances, I want to provide an image with
the specific properties or a flavor with the specific extra specs which will
allow users to boot instances to ensure that their instances run on
an SEV-ES-capable compute host with SEV-ES encryption, instead of SEV
encryption, enabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud user, in order to reduce data leakage risks further, I want to
be able to boot VM instances with SEV-ES functionality, instead of SEV
functionality, enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose extending the existing implementation to support launching instances
with SEV functionality.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV-ES capabilities, which checks the following items.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The presence of the following XML in the response from a libvirt
&lt;a class="reference external" href="https://libvirt.org/html/libvirt-libvirt-domain.html#virConnectGetDomainCapabilities"&gt;virConnectGetDomainCapabilities()&lt;/a&gt;
API call &lt;a class="reference external" href="https://libvirt.org/git/?p=libvirt.git;a=commit;h=6688393c6b222b5d7cba238f21d55134611ede9c"&gt;indicates that both QEMU and the AMD Secure Processor
(AMD-SP) support SEV functionality&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt; &lt;span class="n"&gt;supported&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Also the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxESGuests&lt;/span&gt;&lt;/code&gt; field should be present and its value should be
a positive (non-zero) value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/sys/module/kvm_amd/parameters/sev_es&lt;/span&gt;&lt;/code&gt; should have the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Y&lt;/span&gt;&lt;/code&gt;
to indicate that the kernel has SEV capabilities enabled.  This
should be readable by any user (i.e. even non-root).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check QEMU version to determine whether the available QEMU binary supports
SEV-ES.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait to os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the libvirt driver &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update the ProviderTree object&lt;/a&gt;
with the correct inventory for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource class
for both SEV and SEV-ES. To represent the slots dedicated for SEV and SEV-ES,
nested resource providers are created per-model:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+------------+&lt;/span&gt;     &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt; &lt;span class="o"&gt;+--+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ES&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The SEV RP is named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;nodename&amp;gt;_amd_sev&lt;/span&gt;&lt;/code&gt; and the SEV-ES RP is named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;nodename&amp;gt;_amd_sev_es&lt;/span&gt;&lt;/code&gt;, so that the RP names are unique in the cluster.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV and SEV-ES have separate limits of guest numbers, because ASIDs are
allocated for ES guests and non-ES guests exclusively, from the total
ASIDs available. Minimum ASID for SEV (non-ES) guests, which is
effectively same as maxumum ASID for ES guests, should be configured in
BIOS (or UEFI) to use SEV-ES. A new validation to detect insufficient
ASIDs may be implemented.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV-SNP uses the same ASID pool for ES by default when cyphertext hiding
is not requested, and the new trait (such as HW_CPU_AMD_SEV_SNP) may be
added to the existing SEV-ES RP when SEV-SNP support is added with
a separate SEV-SNP RP with the trait corrsponding to the cyphertext hiding
feature:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+------------+&lt;/span&gt;     &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt; &lt;span class="o"&gt;+--+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ES&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_SNP&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+-----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SNP&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_SNP_CH&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+----+&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+----+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that SEV-SNP support is out of the current scope and this design
needs further dicsussion when the support is actually implemented. It is
described here to explain the potential plan to extend the RP structure
in the future.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model&lt;/span&gt;&lt;/code&gt; parameter in flavor
extra specs, and a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model&lt;/span&gt;&lt;/code&gt; image property. When
either of these is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt; along with the parameter/propery to
enable memory encryption, it would be internally translated to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV_ES=required&lt;/span&gt;&lt;/code&gt; which would be added to the flavor extra
specs in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; object. If these new model parameter/property is
absent or set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev&lt;/span&gt;&lt;/code&gt; then it would be translated to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV=required&lt;/span&gt;&lt;/code&gt;. If conflicting models are requested by
the instance flavor and the instance image (for example the flavor has
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model=amd-sev&lt;/span&gt;&lt;/code&gt; but the image has
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model=amd-sev-es&lt;/span&gt;&lt;/code&gt;) then the request is rejected. Also
the request should be rejected when memory encryption is not requested but
a memory encryption model is requested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the libvirt driver to include extra XML in the guest’s domain
definition when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model&lt;/span&gt;&lt;/code&gt; parameter in flavor extra
spec or the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model&lt;/span&gt;&lt;/code&gt; image property is present and
is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt;. The extra XML is mostly similar to the one used in
SEV, but its guest policy field needs the SEV-ES bit (bit 2) enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Guest attestation is currently out of our scope. Because &lt;a class="reference external" href="https://libvirt.org/kbase/launch_security_sev.html#guest-attestation-for-sev-sev-es-from-a-trusted-host"&gt;the existing
feature for guest attestation&lt;/a&gt;
heavily depends on hypervisor features and is not suitable for confidential
computing use case where users do not trust hypervisors. We aim to implement
the guest attestation feature once SEV-SNP is generally available, because
SEV-SNP provides a better mechanism for guest attestation, using the special
device presented to guest machines to obtain attestation reports.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The end user will harness SEV-ES through the existing mechanisms of resources
in flavor extra specs and image properties.&lt;/p&gt;
&lt;p&gt;Also &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html#impermanent-limitations"&gt;the limitations of AMD SEV-encrypted guest&lt;/a&gt;
are applied when SEV-ES is used.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No performance impact on nova is anticipated.&lt;/p&gt;
&lt;p&gt;Performance impact for the other parts are same as the existing SEV support
feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In order for users to be able to use SEV-ES, the operator will need to
perform the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy SEV-ES-capable hardware as nova compute hosts.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;AMD EPYC 7xx2 (Rome) or later&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set minimum ASID for SEV (non-ES) guests in BIOS (or UEFI) to a value greater
than 0.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If SEV-enabled instancs are already launched in the compute node, enough
ASIDs should be reserved for SEV.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that they have an appropriately configured software stack, so
that the various layers are all SEV-ES ready:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;kernel &amp;gt;= 4.16&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;= 6.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libvirt &amp;gt;= 8.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ovmf &amp;gt;= commit 7f0b28415cb4 2020-08-12&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV-ES enabled guests can be launched by libvirt &amp;gt;= 4.5, but detection of
maximum number of SEV-ES guests via domain capability API requires libvirt
&amp;gt;= 8.0.0 .&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A cloud administrator will need to define SEV-ES-enabled flavors as described
above, unless it is sufficient for users to define SEV-ES-enabled images.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;[libvirt] num_memory_encrypted_guests&lt;/cite&gt; option is effective only for SEV,
but a new option for SEV-ES is NOT added. Instead, the detection capability in
libvirt is required to use SEV-ES. The &lt;cite&gt;num_memory_encrypted_guests&lt;/cite&gt; option
will be deprecated to reduce complexity.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kajinamit (irc: tkajinam)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait for os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV-ES capabilities as detailed above and reshaping
of existing MEMO_ENCRYPTION_CONTEXT resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property to ImageMeta object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update scheduler util to request &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property or
the equivalent flavor extra spec is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update libvirt driver to set the SEV-ES policy bit when the property is
present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update image property schema in glance to validate the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unit tests and functional tests should be added according to new logic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="future-work"&gt;
&lt;h3&gt;Future work&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Special hardware which supports SEV-ES for development, testing, and CI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recent versions of the hypervisor software stack which all support
SEV-ES, as detailed in &lt;a class="reference internal" href="#other-deployer-impact"&gt;Other deployer impact&lt;/a&gt; above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fakelibvirt&lt;/span&gt;&lt;/code&gt; test driver will need adaptation to emulate
SEV-ES-capable hardware.&lt;/p&gt;
&lt;p&gt;Corresponding unit/functional tests will need to be extended or added
to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;detection of SEV-ES-capable hardware and software, e.g. perhaps as an
extension of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.functional.libvirt.test_report_cpu_traits.LibvirtReportTraitsTests&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the use of a trait to include extra SEV-specific libvirt domain XML
configuration, e.g. within
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.unit.virt.libvirt.test_config&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the entry in &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/support-matrix.html"&gt;the Feature Support Matrix&lt;/a&gt;,
to explain now AMD SEV-ES is supported in addition to AMD SEV.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the existing &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html"&gt;AMD SEV&lt;/a&gt; guide to include
information about SEV-ES.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other non-nova documentation should be updated too:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/os-traits/latest/"&gt;documentation for os-traits&lt;/a&gt; should be extended
where appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/sev"&gt;AMD SEV landing page&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/55766.PDF"&gt;AMD SEV-KM API Specification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/AMDESE/AMDSEV/"&gt;AMD SEV github repository containing examples and tools&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://events17.linuxfoundation.org/sites/events/files/slides/AMD%20SEV-ES.pdf"&gt;Slides from the 2017 Linux Security Summit describing SEV and
preliminary performance results&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#sev"&gt;libvirt’s SEV options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Sep 2025 00:00:00 </pubDate></item><item><title>Remove legacy v2.0 API</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/implemented/deprecate-v20-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-v20-api"&gt;https://blueprints.launchpad.net/nova/+spec/remove-v20-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Remove the legacy v2.0 API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova introduced the v2.1 API over a decade ago. Since that time, we have
continued to support the legacy v2.0 API, which was reimplemented as a shim
around the v2.1 API. A decade is a long time, and the Compute API has grown and
changed significantly over this time, hitting the 100th microversion in the
Epoxy (2025.1) release. Deploying and maintaining the legacy API has a cost and
there is no good reason why anyone would continue to use this over even the
base microversion. It is also mostly undocumented for an end-user perspective.
We should deprecate it so that we can remove it.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a developer, I no longer want to concern myself with potential differences
between v2.0 and v2.1.&lt;/p&gt;
&lt;p&gt;As a developer of deployment tooling, I would like to be able to stop deploying
an additional, unused endpoint.&lt;/p&gt;
&lt;p&gt;As a library developer, I would like to able to ignore the v2 API without
feeling bad for doing so.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Change the API status to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEPRECATED&lt;/span&gt;&lt;/code&gt;. This will cause keystoneauth1 and
recent versions of Gophercloud to ignore the API unless the user opts into it.
This is a strong signal to users that the API is not long for the world, and
will allow us to remove it in the H release.&lt;/p&gt;
&lt;p&gt;Update all tests to remove confusing references to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/v2&lt;/span&gt;&lt;/code&gt; path. In most
cases, these are irrelevant since we call controllers directly and the path
part of the URL is ignored, but updating things will make things clearer.&lt;/p&gt;
&lt;p&gt;A “do not merge (DNM)” patch will be proposed removing the v2 API. This will
serve to highlight any places we have missed things in the unit or functional
tests.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to pretend we support this in a meaningful way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The root version document will not report status &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEPRECATED&lt;/span&gt;&lt;/code&gt; for the v2 API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None. All known clients use and rely on the microversioned endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Negligible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployment tooling will be encouraged to stop create a legacy v2 endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The v2 API will no longer need to be considered when undertaking work on the
API. Future changes to the API frameworks used will become somewhat easier.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The v2 legacy API will be deprecated. As such, applications that rely on this
and use libraries that ignore deprecated APIs (like keystoneauth and recent
Gophercloud) will need to be reworked to use the v2.1 API or to opt-in to the
v2 API. It is expected that there are few to none of these applications in the
wild nowadays.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mark the API as deprecated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update tests to use the v2.1 API or remove paths where irrelevant&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update docs to reflect deprecation and future plans for removal&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests should cover this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;References to the v2 API will be updated to highlight the deprecation and
future plans for removal.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Sep 2025 00:00:00 </pubDate></item><item><title>Support for “one time use” devices</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/implemented/one-time-use-devices.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/one-time-use-devices"&gt;https://blueprints.launchpad.net/nova/+spec/one-time-use-devices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As the use of direct-passthrough accelerator devices increases, so does the
need for some sort of post-use cleaning workflow between tenants. A NIC that
is passed directly through to a guest may need to have known-good firmware
re-written to it to make sure the previous user hadn’t violated it in some
way. A GPU might have sensitive residue in memory that needs to be zeroed.
An NVMe device is a storage medium that needs to be wiped or discarded.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there is no good way for operators to define and execute a
device-cleaning workflow outside of Nova. Further, Nova does not intend to
take on such tasks itself, in support of the long-term “no more orchestration”
goal.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to provide passthrough devices to instances with known-
safe firmware and device state.&lt;/p&gt;
&lt;p&gt;As a special-purpose cloud operator, I may have specialized hardware that
requires special handling after use (power or bus resets, config
initialization, etc).&lt;/p&gt;
&lt;p&gt;As a cloud operator, I want to provide fast direct-passthrough storage support,
but without risking information leakage between tenants.&lt;/p&gt;
&lt;p&gt;As a cloud operator, I want to check the write-wear indicator on my passthrough
NVMe devices after each user to avoid returning devices over the safety
threshold to be allocated.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova will support “one time use” devices. That is a device where we will
allocate it for a new instance only once. When that instance is deleted, the
device will not be returned to an allocatable state automatically (as would
normally happen) and instead remain in a reserved state until some action is
taken by the operator’s own workflow to mark it as usable again. Making sure
such a device is not re-allocatable (until cleaned) is a potentially very
security-sensitive step that can not be missed, and it makes sense for Nova
to do this itself, even though it will not take on the actual task of doing
any device cleaning.&lt;/p&gt;
&lt;p&gt;The annotation mechanism here will utilize the &lt;cite&gt;reserved&lt;/cite&gt; inventory count,
on top of PCI-in-placement. Basically, when Nova goes to allocate the device
for the instance, it will follow up with a bump of the &lt;cite&gt;reserved`&lt;/cite&gt; count. When
we go to de-allocate the device, we will not touch the &lt;cite&gt;reserved&lt;/cite&gt; count, thus
leaving the resource provider for the device fully-reserved (and thus not
allocatable).&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is expected to be used for PCI-in-placement and PF devices only due to
the one-to-one resource provider accounting. A future change could enable
this for VFs through another mechanism if we determine a need.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Through whatever workflow the operator decides, they can clean the device, and
decrement the &lt;cite&gt;reserved&lt;/cite&gt; count once they are ready for the device to rejoin
the pool of allocatable devices again. This would likely be listening to
notifications for deleted instances and scheduling such cleaning.&lt;/p&gt;
&lt;p&gt;We will also introduce a new trait (tentatively called &lt;cite&gt;HW_ONE_TIME_USE&lt;/cite&gt;) that
nova will add to resource providers that it is managing as one-time-use. This
will make it easier for operators to survey all the device providers that are
&lt;em&gt;potentially&lt;/em&gt; in need of cleaning. This will not convey whether or not cleaning
is required (which is signaled by total=1,reserved=1,used=0) but rather that
this device &lt;em&gt;may&lt;/em&gt; need cleaning if the conditions are correct.&lt;/p&gt;
&lt;section id="implementation"&gt;
&lt;h3&gt;Implementation&lt;/h3&gt;
&lt;p&gt;The reservation of a device (i.e. “burning” its one-time-use) will happen in
the compute node, (temporally) near where we do the claim and accounting in
the PCI tracker. This will minimize the window for failure after which the
device will be “burned” but not actually used by the instance. At the end of
&lt;cite&gt;instance_claim()&lt;/cite&gt; in the resource tracker, we currently call &lt;cite&gt;_update()&lt;/cite&gt;
which calls &lt;cite&gt;_update_to_placement()&lt;/cite&gt;. There, we do some inventory and
allocation healing, including of placement-tracked PCI devices. Within this
inventory-healing routine, we will reserve PCI devices that are allocated since
we are already auditing (and healing/updating) inventory as needed.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;From this point on, we will use the term “burned” to refer to a device that
has been reserved such that it will not be re-allocated. This happens before
the point at which the instance is able to run with it (in all situations)
and remains in that state until an external action drops the reserved count
back to zero. In other words, “burned” means &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved=total&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;By doing this in the above described way we will get synchronous reservation
of the devices (i.e. it will happen before the instance starts running) as
late as is reasonable. We will also get the ability to “heal” already-
allocated devices into reserved state if they happen to be marked as one-time-
use by the administrator at a later time.&lt;/p&gt;
&lt;p&gt;Move operations will function similarly, as the &lt;cite&gt;_move_claim()&lt;/cite&gt; method also
calls &lt;cite&gt;_update()&lt;/cite&gt; synchronously after the local claims are completed. It should
be noted that a move of an instance with a one-time-use device will “burn” the
device on the destination as soon as it starts running there (i.e. when it
reaches the verify state) and a revert will not “un-burn” it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="lifecycle-operations"&gt;
&lt;h3&gt;Lifecycle Operations&lt;/h3&gt;
&lt;p&gt;Technically one-time-use devices should be able to fully participate in all of
the instance lifecycle operations. There are some caveats however, so a few
cases are discussed below:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Rebuild: The device can be re-used in place without any other action&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evacuate: The original device will have been “burned” when the instance was
booted and will remain as such after the original host is recovered and it
removes the allocation for the original instance. The process of evacuation
will allocate and burn a new device on the new host during the boot process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cold migrate: A new device will allocated on the destination when the
instance is being started there. Once the instance reaches the verify state,
the destination’s new device will be burned. On confirm, the source device
will remain burned, and on revert, the destination device will have been
burned. Note that state (i.e. data) on a stateful device will not be copied
by Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live migrate: If the device is already live migratable, then it will be be
allowed, with the source device remaining “burned” after the operation
completes and of course the new device on the destination will be burned
in the process of the migration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We will need a change in placement to allow over-subscribed resource
providers to progress “towards safety”, meaning “become less
over-subscribed”. For one-time-use devices we must be allowed to swap the
instance’s allocation for the migration UUID on the source node, even though
the provider is already technically over-subscribed due to the device being
reserved. Note that this is already a problem in Nova/Placement and we have
multiple bugs reported against this, where a change in allocation ratio
resulting in over-subscription will prevent operators from migrating
instances away. We need to fix this anyway, and that fix will also apply to
one-time-use devices. Until then, migrate operations (cold, resize, and live)
will be (implicitly) blocked for one-time-use devices. Fixing this will be
slightly outside the scope of this spec, but expect to be completed in
parallel or just afterwards.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Evacuation without consulting the scheduler may result in us sending an
instance to a host requesting a PCI device for which there was no prior
check for whether it is allocatable (i.e. already burned). We need to make
sure that whatever happens on the compute node in this case will fail before
assigning the device to an instance (which should happen during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ResourceTracker._update()&lt;/span&gt;&lt;/code&gt; as part of the allocation healing).&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative is to do nothing and continue to operate as we do today. Nova
intentionally does not provide any device cleaning ability, nor any real hooks
or integration for operators desiring it.&lt;/p&gt;
&lt;p&gt;Another alternative is to say that this is in the scope of Cyborg, it is. Nova
officially recognizes Cyborg as the solution for external, stateful device
prep, cleaning, and lifecycle management and this does not change that. The
one-time-use-devices idea sits somewhere in the middle of “do nothing” and
“do it in Cyborg” in that it’s a _very_ small change to nova to allow an
external integration for which we have existing APIs for people to do what
they need in a simpler case. Certainly from the perspective of an operator
where support for their device does not exist in Cyborg, a simpler workflow
would be easier to craft a homegrown solution. For an operator with bespoke
(maybe scientific) hardware, requiring them to write a full Cyborg driver in
order to call a shell script after each use is a big ask.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;There should be no data model impact if we use the existing PCI &lt;cite&gt;dev_spec&lt;/cite&gt; to
flag a device as &lt;cite&gt;one_time_use=(yes|no)&lt;/cite&gt;. This is a similar approach to the
recent migrate-vfio-devices-using-kernel-variant-drivers spec which allows
operators to flag them as &lt;cite&gt;live_migratable=(yes|no)&lt;/cite&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;No direct security impact, although it will theoretically allow operators to
improve security of device-passthrough workloads by sanitizing or
re-initializing their devices between uses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None (invisible to users).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This will involve a single additional call to placement to update the
inventory after we allocate the device. This should be negligible in terms of
performance impact, and the error handling will be identical to that of the
case where we fail to do the allocation itself.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers who do not wish to use this feature will not be impacted. Those
that do will be able to enable this via config for their PCI devices and
write their own external integrations based on the assumption that devices
will remain reserved after allocation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="id1"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Parse &lt;cite&gt;one_time_use&lt;/cite&gt; from &lt;cite&gt;[pci]dev_spec&lt;/cite&gt; config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add code to bump reserved count when we update allocations and inventories
for the PCI device in placement in the &lt;cite&gt;instance_claim()&lt;/cite&gt; path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add documentation and a sample cleanup listener script&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Work on squashing placement &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1943191"&gt;bug_1943191&lt;/a&gt; (probably in parallel)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This has a soft dependency on a fix to Placement that allows swapping an
allocation while over-subscribed. While not strictly required, fixing this
long-standing issue will enable cold migration of one-time-use devices.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This will be tested fully in unit/functional tests since it requires a real
device to test with tempest.&lt;/p&gt;
&lt;p&gt;One-off testing with real devices will be performed locally during review and
submission.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operator documentation will be added explaining the meaning of the flag, and
the guarantees it makes that the operators can rely on. A sample script for
processing device cleanup will be provided as a sample to start from, but
extensive documentation on how to that robustly will be left to the consumer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;The mechanism for tagging devices is nearly identical to this recent effort:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/migrate-vfio-devices-using-kernel-variant-drivers.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/migrate-vfio-devices-using-kernel-variant-drivers.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Sep 2025 00:00:00 </pubDate></item><item><title>Policy Manager Role Default</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/implemented/policy-manager-role-default.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/policy-manager-role-default"&gt;https://blueprints.launchpad.net/nova/+spec/policy-manager-role-default&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#phase-3"&gt;SRBAC goal phase-3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A project-manager can use project-level management APIs and is denoted by
someone with the manager role on a project. It is intended to perform
more privileged operations than project-member on its project resources.
A project-manager can also perform any operations allowed to a project-member
or project-reader.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, compute API policy default has admin (admin in all project),
project member, and project reader roles. But there are many project level
APIs which should be default to user who are more privileged than normal
user (member, reader role user). Instead of allowing such APIs to global
admin, we should have more privileged user within project.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Keep project level management APIs to someone who is less privileged than admin
and more privileged than project member role.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Keystone introduced a new role ‘manager’ role at project level. A
project-manager can use project-level management APIs and intend
to perform more privileged operations than project-member on its
project resources.&lt;/p&gt;
&lt;p&gt;A project-manager can use project-level management APIs and is denoted
by someone with the manager role on a project. It is intended to perform
more privileged operations than project-member on its project resources.
A project-manager can also perform any operations allowed to a
project-member or project-reader (this is handled by the keystone role
implication so that the admin role implies manager, the manager role
implies member, the member role implies reader). One good example for Nova
to use manager role is in locking and unlocking an instance.&lt;/p&gt;
&lt;p&gt;project-manager persona in the policy check string:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"project_manager"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"role:manager and project_id:&lt;/span&gt;&lt;span class="si"&gt;%(project_id)s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Default rule for project-level management APIs."&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Using it in policy rule (with admin + manager access): (because we want to
keep legacy admin behavior same we need to continue giving access of
project-level management APIs to admin role too.)&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:os-migrate-server:migrate&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'role:admin or ('&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'role:manager and project_id:&lt;/span&gt;&lt;span class="si"&gt;%(project_id)s&lt;/span&gt;&lt;span class="s1"&gt;)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Cold migrate a server without specifying a host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/servers/&lt;/span&gt;&lt;span class="si"&gt;{server_id}&lt;/span&gt;&lt;span class="s1"&gt;/action (migrate)'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="below-apis-policy-will-be-default-to-project-manager-or-admin-role"&gt;
&lt;h3&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROJECT_MANAGER_OR_ADMIN&lt;/span&gt;&lt;/code&gt; role&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Current default: ADMIN -&amp;gt; New default: PROJECT_MANAGER_OR_ADMIN:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate’ (“Cold migrate a server without
specifying a host”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:force_complete’ (“Force an in-progress
live migration for a given server “)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:delete’ (“Delete(Abort) an in-progress
live migration”)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Current default: PROJECT_MEMBER_OR_ADMIN -&amp;gt; New
default: PROJECT_MANAGER_OR_ADMIN:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is making the below APIs more restrictive. Currently they are
allowed for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; users but after this change, it
will be allowed for ‘manager’ and ‘admin’ users (disallowed for ‘member’
user).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:restore’ (“Restore a soft deleted server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:force’ (“Force delete a server before
deferred cleanup”)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Introducing new policy to allow more operation for ``manager`` users:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;There are some APIs (listed below) which should be allowed for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;manager&lt;/span&gt;&lt;/code&gt; user, but we have single policy to perform operation (migrate
server) to specific host or return host info in API response. To keep host
specific operation/info to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; and rest other to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin-or-manager&lt;/span&gt;&lt;/code&gt;,
we need to introduce the separate new policy for host specific things
which will default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; (means no change for host specific things)
and existing policy will be used for non-host things and will default to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin-or-manager&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Live migrate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Existing policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-migrate-server:migrate_live&lt;/span&gt;&lt;/code&gt; (live migrate server)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default changing from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROJECT_MANAGER_OR_ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-migrate-server:migrate_live:host&lt;/span&gt;&lt;/code&gt; (live migrate
server to specific host)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List server (in-progress live) migration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Existing policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:servers:migrations:index&lt;/span&gt;&lt;/code&gt; (Lists in-progress live
migrations for a given server)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default changing from: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROJECT_MANAGER_OR_ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:servers:migrations:index:host&lt;/span&gt;&lt;/code&gt; (Lists in-progress live
migrations for a given server with host info)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List migrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Existing policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-migrations:index&lt;/span&gt;&lt;/code&gt; (List migrations without
host info)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default changing from: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROJECT_MANAGER_OR_ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-migrations:index:host&lt;/span&gt;&lt;/code&gt; (List migrations with
host info)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-migrations:index:all_projects&lt;/span&gt;&lt;/code&gt; (List migrations
cross projects)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Default: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ADMIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This APIs allow to list migration for all or cross projects. Because
we are opening current policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;index&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt; &lt;span class="pre"&gt;manager&lt;/span&gt;&lt;/code&gt; user,
we need a separate new policy to control that only &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; can acess
all or cross project migrations and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt; &lt;span class="pre"&gt;manager&lt;/span&gt;&lt;/code&gt; can only
access their own project migrations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Currently, project member can perform the below server actions. It might
not be good idea to add more strict access control on them.  We will
continue allow project member user to perform these action. With keystone
implied roles, project manager can also perform the below actions in their
project servers.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-lock-server:lock’ (“Lock a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-lock-server:unlock’ (“Unlock a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-pause-server:pause’ (“Pause a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-pause-server:unpause’ (“Unpause a paused server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-rescue’ (“Rescue a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-unrescue’ (“Unrescue a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-suspend-server:resume’ (“Resume suspended server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-suspend-server:suspend’ (“Suspend server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:resize’ (“Resize a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:confirm_resize’ (“Confirm a server resize”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:revert_resize’ (“Revert a server resize”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:reboot’ (“Reboot a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:rebuild’ (“Rebuild a server”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:rebuild:trusted_certs’ (“Rebuild a server with
trusted image certificate IDs”)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep admin or member do all project level management operation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Below APIs policy default will be changed:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current default: ADMIN -&amp;gt; New default: PROJECT_MANAGER_OR_ADMIN:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:force_complete’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:delete’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate_live’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:index’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrations:index’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Current default: PROJECT_MEMBER_OR_ADMIN -&amp;gt; New
default: PROJECT_MANAGER_OR_ADMIN:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:restore’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:force’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Introducing below new policies default to PROJECT_MANAGER_OR_ADMIN:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate_live:host’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:index:host’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrations:index:host’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrations:index:all_projects’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Provide more secure RBAC by adding project manager role to handle project
resources management activities.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Below API policies default will not be allowed for ‘member’ role user,
they need ‘manager’ role in their project to continue performing these
operations.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:restore’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:force’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The below APIs policy default is changed from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;manager&lt;/span&gt;&lt;/code&gt; role,
make sure to override the required permission in policy.yaml or move the
deployment to the new defaults.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:restore’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete:force’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;New policies are introduced to control the host specific operation/information.
Below policies defaults are changed to allow the project ‘manager’ role also.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate_live’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:index’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have overridden the above policies with other permission, then override
the same permission for the new policies also:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate_live:host’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:index:host’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New APIs must add policies that follow the new pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;New policies are introduced to control the host specific operation/information.
Below policies defaults are changed to allow the project ‘manager’ role also.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate_live’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:index’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have overridden the above policies with other permission, then override
the same permission for the new policies also:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-migrate-server:migrate_live:host’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:migrations:index:host’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmaan&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmaan&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Modify the project-level management APIs defaults to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;manager&lt;/span&gt;&lt;/code&gt; role&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify policy rule unit tests to use service and manager role token&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move Tempest tests of changed policies to new defaults.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Modify or add the policy unit tests.
Move Tempest tests of changed policies to new defaults.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;manager&lt;/span&gt;&lt;/code&gt; role API defaults will be updated in policy rule document
as well as in policy sample file.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Sep 2025 00:00:00 </pubDate></item><item><title>Policy Service Role Default</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/implemented/policy-service-role-default.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/policy-service-role-default"&gt;https://blueprints.launchpad.net/nova/+spec/policy-service-role-default&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally all internal service-to-service APIs should not be accessible
by admin or end user by default. From policy defaults it should be
clear which APIs are supposed to be used by admin or end user and
which is for internal service-to-service APIs communication.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, internal service-to-service communication APIs have their
default policy as either admin or project roles which means operators
need to assign the admin or project roles to their service users.
That service user having admin or project role access is poor security
practice as they can perform admin or project level operations.&lt;/p&gt;
&lt;p&gt;Another problem is that APIs which are meant to only be used by internal
services are able to be called by regular users and human admins. Requiring
(and allowing only) a service role for these APIs help avoid intentional
and accidental abuse.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I want to keep &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user to access
service-to-service APIs with least privilege.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We need to make sure all the policy rules for internal service-to-service
APIs are default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role only. Example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:os-server-external-events:create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'role:service'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'project'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Keystone’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role is kept outside of the existing role hierarchy
that includes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader&lt;/span&gt;&lt;/code&gt;. Keeping the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
role outside the current hierarchy ensures we’re following the principle
of least privilege for service accounts.&lt;/p&gt;
&lt;p&gt;We need to make all the service-to-service APIs which are &lt;em&gt;only&lt;/em&gt; suitable
for services default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role only. But we might have some cases
where APIs are both intended for service usage, as well as admin (any other
user role) usage. For such policy rules we need to default them to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
as well as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; (or any other user role) role. For example,
‘role:admin or role:service’&lt;/p&gt;
&lt;p&gt;As Nova have dropped the system scope implementation, service-to-service
communication with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role will be done with project scope token
(which is currently done in devstack setup).&lt;/p&gt;
&lt;p&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:delete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-volumes-attachments:swap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-server-external-events:create&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep the service-to-service APIs default same as it is and expect operators
to take care of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role users access permissions by overriding
it in the policy.yaml.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:delete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-volumes-attachments:swap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-server-external-events:create&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Easier to understand service-to-service APIs policy and restricting them to
least privilege.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If service-to-service APIs are used by the admin or end user then make
sure to override the required permission in policy.yaml because by default
they will be accessed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New APIs must add policies that follow the new pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;If service-to-service APIs are used by the admin or end user then make
sure to override the required permission in policy.yaml because by default
they will be accessed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user only. If deployment
overrides these policies then, they need to start considering the new
default policy rules.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Modify the service-to-service APIs defaults&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify policy rule unit tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Modify or add the policy unit tests.&lt;/p&gt;
&lt;p&gt;Add a job enabling the new defaults and run the tempest tests to make sure
existing service-service APIs communication work fine. If needed modify the
token used by services as per the new defaults.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;API Reference should be updated to add all the service-service APIs under
separate section and mention about &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role as their default.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Sep 2025 00:00:00 </pubDate></item><item><title>OpenAPI Schemas</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/approved/openapi.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/openapi-3"&gt;https://blueprints.launchpad.net/nova/+spec/openapi-3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to start documenting our APIs in an industry-standard,
machine-readable manner. Doing so opens up many opportunities for both
OpenStack developer and OpenStack users alike, notably the ability to both
auto-generate and auto-validate both client tooling and documentation alike. Of
the many API description languages available, OpenAPI (fka “Swagger”) appears
to be the one with both the largest developer mindshare and the one that would
be the best fit for OpenStack due to the existing tooling used in many
OpenStack services, thus we would opt to use this format.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is a continuation of a spec that was previously approved in Dalmatian
(2024.2) and Epoxy (2025.1). We merged all of the groundwork for this in
Dalmatian and worked on the response bodies schemas in Epoxy but did not
get them completed.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The history of API description languages has been mainly a history of
half-baked ideas, unnecessary complication, and in general lots of failure.
This history has been reflected in OpenStack’s own history of attempting to
document APIs, starting with our early use of WADL through to our experiments
with Swagger 2.0 and RAML, leading to today’s use of our custom &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
project, built on reStructuredText and Sphinx.&lt;/p&gt;
&lt;p&gt;It is only in recent years that things have started to stabilise somewhat, with
the development of widely used API description languages like OpenAPI, RAML and
API Blueprint, as well as supporting SaaS tools such as Postman and Apigee.
OpenAPI in particular has seen broad adoption across multiple sectors, with
sites as varied as &lt;a class="reference external" href="https://blog.cloudflare.com/open-api-transition"&gt;CloudFlare&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/github/rest-api-description"&gt;GitHub&lt;/a&gt; providing OpenAPI schemas for
their APIs. OpenAPI has evolved significantly in recent years and now supports
a wide variety of API patterns including things like webhooks. Even more
beneficial for OpenStack, OpenAPI 3.1 is a full superset of JSON Schema meaning
we have the ability to re-use much of the validation we already have.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an end user, I would like to have access to machine-readable, fully
validated documentation for the APIs I will be interacting with.&lt;/p&gt;
&lt;p&gt;As an end user, I want statically viewable documentation hosted as part of the
existing docs site without requiring a running instance of Nova.&lt;/p&gt;
&lt;p&gt;As an SDK/client developer, I would like to be able to auto-generate bindings
and clients, promoting consistency and minimising the amount of manual work
needed to develop and maintain these.&lt;/p&gt;
&lt;p&gt;As a Nova developer, I would like to have a verified API specification that I
can use should I need to replace the web framework/libraries we use in the
event they are no longer maintained.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This effort can be broken into a number of distinct steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new decorator for removed APIs and actions&lt;/p&gt;
&lt;p&gt;We have a number of APIs and actions that no longer have backing code and
return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;(Bad&lt;/span&gt; &lt;span class="pre"&gt;Request)&lt;/span&gt;&lt;/code&gt;, respectively. We
will not add schemas for these in the initial attempt at this so we need some
mechanism to indicate this. We will add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;removed&lt;/span&gt;&lt;/code&gt; decorator that will
highlight these removed APIs and indicate the version they were removed in
and the reason for their removal. We can later use this as a heuristic in our
tests to skip schema checks for these methods.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This was completed in Dalmatian (2024.2)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing request body and query string schemas&lt;/p&gt;
&lt;p&gt;There is already good coverage of both request bodies and query string
parameters but it is not complete. A list of incomplete schemas is given at
the end of this section. The additional schemas will merely validate what is
already allowed, which will mean extensive use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"additionalProperties":&lt;/span&gt;
&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; or empty schemas. Put another way, an API that currently ignores
unexpected request body fields or query string parameters will continue to
ignore them. We may wish to make these stricter, as we did for most APIs in
microversion 2.75, but that is a separate issue that should be addressed
separately.&lt;/p&gt;
&lt;p&gt;Once these specs are added, tests will be added to ensure all non-deprecated
and non-removed API resources have appropriate schemas.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This was completed in Dalmatian (2024.2)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;
&lt;p&gt;These will be sourced from existing OpenAPI schemas, currently published
at &lt;a class="reference external" href="https://github.com/gtema/openstack-openapi"&gt;github.com/gtema/openstack-openapi&lt;/a&gt;, from &lt;a class="reference external" href="https://github.com/openstack/tempest/tree/c0da6e843a/tempest/lib/api_schema/response/compute"&gt;Tempest’s API schemas&lt;/a&gt;,
and where necessary from new schemas auto-generated from JSON response bodies
generated in tests and manually modified handle things like enum values.&lt;/p&gt;
&lt;p&gt;Once these are added, tests will be added to ensure all non-deprecated and
non-removed API resources have appropriate response body schemas. In
addition, we will add a new configuration option that will control how we do
verification at the API layer, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. This will be an
enum value with three options:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Raise a HTTP 500 (Server Error) in the event that an API returns an
“invalid” response.&lt;/p&gt;
&lt;p&gt;This will be the default in CI i.e. for our unit, functional and
integration tests. This should not be used in production. The help text
of the option will indicate this and we will set the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;advanced&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Log a warning about an “invalid” response, prompting operations to file a
bug report against Nova.&lt;/p&gt;
&lt;p&gt;This will be initial (and likely forever) default in production.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ignore&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Disable API response body validation entirely. This is an escape hatch in
case we mess up.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The development of tooling required to gather these JSON Schema schemas and
generate an OpenAPI schema will not be developed inside Nova and is
therefore not covered by this spec. Nova will merely consume the resulting
tooling for use in documentation. It is intended that the same tool will be
usable across any OpenStack project that uses the same web frameworks
(in Nova’s case, WebOb + Routes).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The impact of middleware that modifies either the request or response will
not be accounted for in this change. This is because these are configurable
and they cannot be guaranteed to exist in a given deployment. Examples
include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sizelimit&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.middlware&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_token&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;keystonemiddleware&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a different tool&lt;/p&gt;
&lt;p&gt;We could use a different tool than OpenAPI to publish our specs. In a manner
of speaking we already do this - albeit not in a machine-readable manner -
through our use of os-api-ref.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because OpenAPI is clearly the best tool for the
It is the most widely used API description language available today and
aligns well with our existing use of JSON Schema for API validation. While it
does not support OpenStack’s microversion API design pattern out-of-the-box,
previous experiments have demonstrated that it is extensible enough to add
this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain these specs out-of-tree&lt;/p&gt;
&lt;p&gt;We could use a separate repo to store and maintain specs for Nova and the
other OpenStack services.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because it prevents us testing the specs on each
commit to Nova and means work that could be spread across multiple teams is
instead focused on one small team. It will result in more bugs and a lag
between changes to the Nova API and changes to the out-of-tree specs. It will
result in duplication of effort across Nova, Tempest, and the specs projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish the spec via an API resource rather than in our docs&lt;/p&gt;
&lt;p&gt;We could publish the spec via a new, unversioned API endpoint such as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/spec&lt;/span&gt;&lt;/code&gt;. A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; request to this would return the full spec, either
statically generated at deployment time or dynamically generated (and then
cached) at runtime.&lt;/p&gt;
&lt;p&gt;This is rejected because it brings limited advantages and multiple
disadvantages. Nova’s API is designed to be backwards-compatible and
non-extensible. As such, a user with the latest version of the spec should be
able to use it to communicate with any OpenStack deployment running a version
of Nova that supports microversions. It is also expected that the “master”
version of the spec will continuously improve as things are tightened up,
documentation is improved, and bugs or mistakes are corrected. We want
consumers of the spec to see these changes immediately rather than wait for
their deployment to be updated. Finally, OpenStack’s previous forays into
discoverable APIs, such as Keystone’s use of JSONHome or Glance’s attempts to
publish resource schemas, have seen limited take-up outside of the projects
themselves. Taken together, this all suggests there is no reason or advantage
to publishing deployment-specific specs and users would be better served by
fetching the latest version of the spec from the api-ref documentation
published on docs.openstack.org (which, one should note, is itself
intentionally unversioned).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no direct REST API impact. Users will see HTTP 500 error if they
set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; and encounter an invalid response,
however, we will not encourage use of this option in production and will
instead focus on validating this ourselves in CI.&lt;/p&gt;
&lt;p&gt;We may wish to address issues that are uncovered as we add schemas, but this
work is considered secondary to this effort and can be tackled separately.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This should be very beneficial for users who are interested in developing
client and bindings for OpenStack. In particular, this should (after an initial
effort in code generation) reduce the workload of the SDK team as well as teams
outside of OpenStack that work on client tooling such as the Gophercloud team.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be a minimal impact on API performance when validation is enabled as
we will now verify both requests and responses for all API resources. Given our
existing extensive use of JSON Schema for API validation, it is expected that
this should not be a significant issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As noted previously, there will be one new config option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. Operators may see increased warnings in their logs due
to incomplete schemas, but most if not all of these issues should be ironed out
by our CI coverage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers working on the API microversions will now be encouraged to provide
JSON Schema schemas for both requests and responses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gtema&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add missing request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add decorator to validate response body schemas against response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The actual generation of an OpenAPI documentation will be achieved via a
separate tool. It is not yet determined if this tool will live inside an
existing project, such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstacksdk&lt;/span&gt;&lt;/code&gt;, or inside a
wholly new project. In any case, it is envisaged that this tool will handle
OpenStack-specific nuances like microversions that don’t map 1:1 to OpenAPI
concepts in a consistent and documented fashion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests will ensure that schemas eventually exist for request bodies, query
strings, and response bodies.&lt;/p&gt;
&lt;p&gt;Unit, functional and integration tests will all work together to ensure that
response body schemas match real responses by setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Initially there should be no impact as we will continue to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
as-is for our &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;api-ref&lt;/span&gt;&lt;/code&gt; docs. Eventually we will replace or extend this
extension to generate documentation from our OpenAPI schema.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;section id="apis-missing-schemas"&gt;
&lt;h3&gt;APIs missing schemas&lt;/h3&gt;
&lt;p&gt;These are the APIs that are currently (as of 2024-04-11, commit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;1bca24aeb&lt;/span&gt;&lt;/code&gt;)
missing API request body schemas and query string schemas.&lt;/p&gt;
&lt;p class="rubric"&gt;Missing request body schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._inject_network_info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._reset_network&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._add_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._remove_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.sync_instances&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._force_delete&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._restore&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.reserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.unreserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LockServerController._unlock&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._associate_host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_host_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_project_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController._disassociate_host_and_project&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.add&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._pause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._unpause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RemoteConsolesController.get_rdp_console&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RescueController._unrescue&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._addSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._removeSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_confirm_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_revert_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._start_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._stop_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve_offload&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._resume&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._suspend&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Missing request query string schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.capacities&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsoleAuthTokensController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorAccessController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPPoolsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.reboot&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.shutdown&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.startup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.search&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.statistics&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.uptime&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaClassSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.defaults&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerDiagnosticsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerPasswordController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerSecurityGroupController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTopologyController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerVirtualInterfaceController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SnapshotController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VersionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We should emphasise that many - but not all - of the aforementioned APIs
are either deprecated or removed. We may wish &lt;em&gt;not&lt;/em&gt; to add schemas for
these, though by doing so we will lose the ability to generate documentation
or clients for these APIs from the OpenAPI spec.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced. Missing query schema and request body schemas added.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish response body schemas.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish response body schemas.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 29 Aug 2025 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2026.1/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;p&gt;If this is adding a new API microversion which alters a response schema, we
will also need a corresponding change in Tempest to add the new schema under
tempest/lib/api_schema/. This is required in order for the new microversion to
be used in Tempest tests. Otherwise, new microversion requests will fail
response schema validation in Tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2026.1 Gazpacho&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 30 Jul 2025 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;p&gt;If this is adding a new API microversion which alters a response schema, we
will also need a corresponding change in Tempest to add the new schema under
tempest/lib/api_schema/. This is required in order for the new microversion to
be used in Tempest tests. Otherwise, new microversion requests will fail
response schema validation in Tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 07 May 2025 00:00:00 </pubDate></item><item><title>vTPM live migration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/approved/vtpm-live-migration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/vtpm-live-migration"&gt;https://blueprints.launchpad.net/nova/+spec/vtpm-live-migration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When Nova first added vTPM support, all non-spawn operations were &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/741500"&gt;rejected&lt;/a&gt; at the API level. Extra
work was necessary to manage the vTPM state when moving an instance. This work
was eventually completed for resize and cold migration, and those operations
were &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/639934/52"&gt;unblocked&lt;/a&gt;.
The blocks on live migration, evacuation, shelving and rescue are &lt;a class="reference external" href="https://docs.openstack.org/nova/2024.2/admin/emulated-tpm.html#limitations"&gt;still in
place&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A TPM device is &lt;a class="reference external" href="https://learn.microsoft.com/en-us/windows-server/get-started/hardware-requirements"&gt;required for certain features&lt;/a&gt;
of Windows Server 2022 and 2025, notably BitLocker Drive Encryption. It’s also
required to run &lt;a class="reference external" href="https://www.microsoft.com/en-us/windows/windows-11-specifications"&gt;Windows 11 at all&lt;/a&gt;. The
inability to live migrate instances with vTPM is a major roadblock for anyone
operating Windows guests in an OpenStack cloud.&lt;/p&gt;
&lt;p&gt;Libvirt support for vTPM live migration now exists (more details in
&lt;a class="reference internal" href="#vtpm-live-migration-2025-2-problem-description"&gt;&lt;span class="std std-ref"&gt;Problem description&lt;/span&gt;&lt;/a&gt;), but Nova changes are
necessary before being able to remove the API block. This spec describes those
changes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;span id="vtpm-live-migration-2025-2-problem-description"/&gt;&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are four aspects to vTPM live migration: shared vs non-shared vTPM state
storage, Libvirt support, and secret management. There is also an adjacent
problem, that - while not related to live migration - can be resolved by the
changes necessary to support live migration: vTPM instances cannot be started
back up by Nova after a compute host reboot.&lt;/p&gt;
&lt;section id="vtpm-state-storage"&gt;
&lt;h3&gt;vTPM state storage&lt;/h3&gt;
&lt;p&gt;vTPM state storage is not the same as instance state storage. The latter can be
configured to be shared, for example on NFS. The former is always non-shared.
Libvirt can be told where to store the vTPM state via the &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#tpm-device"&gt;source&lt;/a&gt; XML element, which Nova
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/config.py#L1146-L1153"&gt;does not support&lt;/a&gt;.
Nova deployments use the Libvirt default vTPM state path. On both Ubuntu and
Red Hat operating systems, this path is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/libvirt/swtpm/&amp;lt;instance&lt;/span&gt;
&lt;span class="pre"&gt;UUID&amp;gt;&lt;/span&gt;&lt;/code&gt;. This path is distinct from the instance state path and can be expected
to never be on shared storage.&lt;/p&gt;
&lt;p&gt;Thus, this spec requires vTPM state storage to be not shared, and declares live
migration with shared vTPM state storage to be untested. This will be
documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="libvirt-support"&gt;
&lt;h3&gt;Libvirt support&lt;/h3&gt;
&lt;p&gt;Though it was impossible to find Libvirt artifacts explicitly demonstrating
vTPM live migration support for non-shared vTPM state storage, as of &lt;a class="reference external" href="https://www.libvirt.org/news.html#v8-10-0-2022-12-01"&gt;version
8.10&lt;/a&gt;, vTPM live
migration with shared vTPM storage is supported, and &lt;a class="reference external" href="https://github.com/stefanberger/swtpm/issues/525#issuecomment-914542936"&gt;this comment&lt;/a&gt;
suggests that for non-shared storage, vTPM live migration has been supported
since version 7.1.0.&lt;/p&gt;
&lt;p&gt;Therefore, this spec requires Libvirt 7.1.0.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="secret-management"&gt;
&lt;h3&gt;Secret management&lt;/h3&gt;
&lt;p&gt;When creating an instance with vTPM, Nova asks a key manager - normally
Barbican - to generate a secret. Crucially, this is done with the user’s token,
and the created secret is owned by the user, with no one else - not even admin
or the Nova service user - being able to read it. Nova then &lt;a class="reference external" href="https://libvirt.org/formatsecret.html"&gt;defines the secret
in Libvirt&lt;/a&gt;, and in the instance XML
references the secret by its UUID. This tells Libvirt to encrypt the instance’s
vTPM state using the contents of that secret as the symmetric key. Nova
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/driver.py#L8077"&gt;undefines the secret&lt;/a&gt;
once the Libvirt domain spawns successfully.&lt;/p&gt;
&lt;p&gt;For vTPM live migration to work, a Libvirt secret with the same UUID and
contents needs to be defined on the destination host so that destination
Libvirt can decrypt the vTPM state. Currently, Nova has no way of doing this.
Live migration is an admin operation, and neither admin nor the Nova service
user have access to the Barbican secret (unless the admin happens to be the
owen of the instance, but that’s an edge case). The Libvirt secret cannot be
read back on the source host either, because it’s defined as &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/host.py#L1115-L1116"&gt;private&lt;/a&gt;
and is undefined once the domain spawns.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="compute-host-reboot"&gt;
&lt;h3&gt;Compute host reboot&lt;/h3&gt;
&lt;p&gt;For the exact same reasons (lack of Barbican secret access and inability to
read the Libvirt secret back from Libvirt), Nova cannot start back up vTPM
instances after a compute host reboot.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a cloud operator, I want to be able to live migrate instances with vTPM
devices, in particular Windows instances.&lt;/p&gt;
&lt;p&gt;As a cloud user, I want to keep the contents of my instance’s vTPM private.
The cloud system should only be able to decrypt it when I request it via my
user token and the system should only keep the decryption secret around for a
limited time. I as a user am willing to accept that such privacy requirements
limit some of the admin initiated lifecycle operations on my instance.&lt;/p&gt;
&lt;p&gt;As a cloud operator, I want vTPM instances on a compute host to start back up
again after a host reboot.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Because the security of the vTPM secret (either in Barbican or in Libvirt)
affects what operations can be performed on an instance, users should be able
to specify what level of security they require, and operators need to specify
what level of security they’re willing to support. There also needs to be a
default level applied to an instance if nothing is explicitly specified.&lt;/p&gt;
&lt;p&gt;Three possible security levels are proposed. They are presented in the table
below.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security&lt;/span&gt;&lt;/code&gt; values&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Mechanism&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Security implications&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Instance mobility&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Only the instance owner has access to the Barbican secret. This is existing
behavior.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is the most secure option, as even the Nova service user and root on
the compute host cannot read the secret.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance is immovable and cannot be restarted by Nova in the event of a
compute host crash or reboot.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The Libvirt secret is persistent and retrievable.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is “medium” security. API-level admins and the Nova service user do
not have access to the secret, but it can be accessed by users with
sufficient privileges on the compute host.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance can be live migrated because Nova can read the secret back
from Libvirt on the source host and send it to the destination over RPC.
Security over the wire is left as the operator’s responsibility, but TLS or
similar is assumed. The instance can also be restarted by Nova in the event
of a compute host crash or reboot for the exact same reason.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The Nova service user owns the Barbican secret.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is the least secure but most flexible option.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance can be live migrated because Nova can download the secret from
Barbican and define it in Libvirt on the destination host. The instance can
also be restarted by Nova in the event of a compute host crash or reboot
for the exact same reason.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Users are able to choose what level they require on their instance by setting
the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt; image property. If this property is not
set, a default can be obtained from the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt; flavor
extra spec. For operators that do not want to deal with flavor explosion as a
consequence of this new extra spec, a new host configuration option is added as
a fallback. Called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]default_tpm_secret_security&lt;/span&gt;&lt;/code&gt; with a default
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt; (which is existing behavior), an instance with no image
property or flavor extra spec will have its host’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security&lt;/span&gt;&lt;/code&gt;
policy persisted in its &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; upon booting on that host.&lt;/p&gt;
&lt;p&gt;Operators are able to specify what level they support by using the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]supported_tpm_secret_security&lt;/span&gt;&lt;/code&gt; config option. This is a
per compute host list option that can take the value of one or more of the
security levels from the previous table. Its default value is all three levels.
These values are exposed as driver capability traits. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt; image property and flavor extra spec are translated
to required traits to match the driver capabilities.&lt;/p&gt;
&lt;p&gt;The behavior of an instance during live migration is defined by its persisted
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt; (either explicitly set by the user, or added by
default by Nova from the host’s config option). Instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt; cannot
be live migrated. For instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;, the source compute host reads
the secret from Libvirt and sends it over RPC to the destination. For instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt;, the destination host downloads the secret from Barbican
and defines it in Libvirt. Because the instance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt;
value translates to a required trait, it’s guaranteed that the destination host
chosen for live migration supports whatever behavior the instance requires.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This is the only version of this spec that covers the essentials: users with
existing instances are informed of the vTPM secret security level set on their
instances by the operator, users of new instances can chose the security level
that they require, and operators can chose which security levels they are
willing to support given the limitations imposed by higher security levels.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetaProps&lt;/span&gt;&lt;/code&gt; Nova object is updated to support the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt; image property. The database schema is unaffected.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;No new microversion. The flavor extra spec validation code is updated to allow
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The main security consequences of this spec are the implications of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; values of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; case, anyone with sufficient access to the compute host can
read vTPM secrets. While this is not great, it’s also something the user opts
in to, and the compute host are assumed to be secured by the cloud operator.&lt;/p&gt;
&lt;p&gt;In the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; case, a compromise of the Nova service user leads to an
exposure of all vTPM secrets. Once again, this is something the user opts in
to, and the Nova service user is assumed to be secure.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A compute service version bump is necessary. When nova-compute starts up with
the new service version, it checks all instances currently on the host. Any
instances created after the service version bump have a value for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt; set in their &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;, either explicitly
by the user or implicitly by Nova as a fallback default, as described in the
&lt;cite&gt;&amp;lt;Proposed change_&amp;gt;_&lt;/cite&gt; section. Any instances without this set are pre-existing
instances, and need to be upgraded. They are upgraded to the value of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]default_tpm_secret_security&lt;/span&gt;&lt;/code&gt; value. Just persisting this in their
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; is not enough - their owner also needs to perform an
operation with their token on the instance so that Nova can either convert the
Libvirt secret to non-private and persistent in the case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;, or create
a new Barbican secret with the same contents, but owned by the Nova service
user, in the case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt;. Operators have no choice but to
communicate this to their users, at which point users have a choice to either
opt in to the new security level, or refuse by not touching their instances or
deleting them outright. In order to see what secret security level has been set
on their instances by the operators, this spec depends on the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/938910"&gt;Image props in
server show&lt;/a&gt;
spec, which will allow users to see the embedded image properties set on their
instance, and determine the vTPM secret security level that way.&lt;/p&gt;
&lt;section id="user-confirmation-mechanism"&gt;
&lt;h4&gt;User confirmation mechanism&lt;/h4&gt;
&lt;p&gt;For existing instances, because a user token is needed to activate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; vTPM secret security policies, the presence of the embedded
image property set on the instances alone will not convey whether the policy
shown is currently active.&lt;/p&gt;
&lt;p&gt;In order to track whether instances’ vTPM secret security policies are
currently active, a new flag &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security_confirmed&lt;/span&gt;&lt;/code&gt; will be set in
the instance &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; with a value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Existing instances will get &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security_confirmed&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; and will
be switched to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; if and when the user reboots their instance. If the
user never touches their instance, it will remain &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;New instances will get &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security_confirmed&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security_confirmed&lt;/span&gt;&lt;/code&gt; will be used internally by Nova
to determine whether to reject an API request for live migration or not. If the
vTPM secret security policy has not been confirmed, Nova API will reject a
request for live migration, preserving legacy behavior for existing instances
in that case.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;notartom, melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt, dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_secret_security&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_secret_security&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]supported_tpm_secret_security&lt;/span&gt;&lt;/code&gt;, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]default_tpm_secret_security&lt;/span&gt;&lt;/code&gt; image properties, flavor extra
specs, and config options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the pre live migration and rollback code to handle secret definition
and cleanup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_security_confirmed&lt;/span&gt;&lt;/code&gt; flag in instance
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bump the service version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the existing API block to only allow live migration of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; instances once the minimum service version has reached the
bumped version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a whitebox/integration test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Libvirt version 7.1.0. This can be enforced dynamically in code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Nova’s functional tests are extended to test the Nova logic using the Libvirt
fixture. This is particularly useful for cases that cannot be easily tested in
a real environment, like rollback.&lt;/p&gt;
&lt;p&gt;The existing &lt;a class="reference external" href="https://opendev.org/openstack/whitebox-tempest-plugin/src/commit/bee34dbb867dc3c107f1262f68a997ef7ccff55a/whitebox_tempest_plugin/api/compute/test_vtpm.py"&gt;whitebox-tempest-plugin vTPM tests&lt;/a&gt;
are extended to test live migration in a real environment with an actual
Libvirt.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Nova’s &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/emulated-tpm.html"&gt;vTPM documentation&lt;/a&gt; is updated
to remove the live migration limitation and explain the usage of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;supported_tpm_secret_security&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default_tpm_secret_security&lt;/span&gt;&lt;/code&gt;
configuration options, as well as the implications of all possible values. The
expectation that vTPM state storage is not shared and that shared vTPM state
storage live migration is untested is made explicit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Empty.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 16 Apr 2025 00:00:00 </pubDate></item><item><title>Enable VFIO devices with kernel variant drivers</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/enable-vfio-devices-with-kernel-variant-drivers.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/enable-vfio-devices-with-kernel-variant-drivers"&gt;https://blueprints.launchpad.net/nova/+spec/enable-vfio-devices-with-kernel-variant-drivers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the necessary steps to enable support for SR-IOV devices
using the new kernel VFIO SR-IOV variant driver interface.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Starting with kernel 5.16 and continuing in subsequent kernels, including
those in Ubuntu 24.04 (Noble Numbat) and future RHEL 10 releases, the SR-IOV
mechanism for sharing Virtual Functions (VFs) with a guest has evolved.&lt;/p&gt;
&lt;p&gt;While the older interfaces are still supported, a new interface using
&lt;a class="reference external" href="https://docs.kernel.org/driver-api/vfio-pci-device-specific-driver-acceptance.html"&gt;variant drivers&lt;/a&gt; has been introduced. Several devices already leverage
this newer variant driver interface.&lt;/p&gt;
&lt;p&gt;As a result, Nova should update its VFIO device support to accommodate
this advancement.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to use SR-IOV devices on Linux distributions that
require variant drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want “legacy” SR-IOV devices support to remain compatible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="description"&gt;
&lt;h3&gt;Description:&lt;/h3&gt;
&lt;p&gt;SR-IOV devices using the variant driver interface can likely be integrated
with Nova by building upon the existing PCI passthrough and SR-IOV support,
combined with several modifications proposed in this specification.&lt;/p&gt;
&lt;p&gt;According to the device documentation, users should configure the devices
to be accessible as PCI Virtual Functions (VFs) identified by their PCI
addresses.&lt;/p&gt;
&lt;p&gt;Subsequently, by following the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/pci-passthrough.html"&gt;Nova documentation on attaching physical PCI
devices to guests&lt;/a&gt;, users should arrive at a main configuration PCI section
that specifies device attributes and aliases.&lt;/p&gt;
&lt;section id="configuring-managed-mode"&gt;
&lt;h4&gt;Configuring managed mode:&lt;/h4&gt;
&lt;p&gt;Users must specify whether the PCI device is managed by libvirt to allow
detachment from the host and assignment to the guest, or vice versa.
The managed mode of a device depends on the specific device and the support
provided by its driver.&lt;/p&gt;
&lt;p&gt;The proposed solution is to add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;managed&lt;/span&gt;&lt;/code&gt; tag to the device
specification.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;managed='yes'&lt;/span&gt;&lt;/code&gt; means that nova will let libvirt to detach the device
from the host before attaching it to the guest and re-attach it to the host
after the guest is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;managed='no'&lt;/span&gt;&lt;/code&gt; means that nova will not request libvirt to detach / attach
the device from / to the host. In this case nova assumes that the operator
configured the host in a way that these VFs are not attached to the host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If not set, the default value is managed=’yes’ to preserve the existing
behavior, primarily for upgrade purposes.&lt;/p&gt;
&lt;p&gt;The behavior, specifically for Nova, assumes that the devices are already
bound to vfio-pci or the relevant variant driver and are directly usable
without any additional operations to enable passthrough to QEMU.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;Incorrect configuration of this parameter may result in host OS crashes.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When this tag is encountered by the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/f98f414f971b6c897bf48781a579730419b5a93d/nova/compute/pci_placement_translator.py#L597-L600"&gt;PCI resource tracker&lt;/a&gt;, the
corresponding information will be stored in the respective PciDevice
object under the extra_info field.
This allows the code responsible for generating the XML definition to
configure the libvirt-managed mode with the appropriate value.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The PciDevice object version remains unchanged.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="sanitize-device-specification"&gt;
&lt;h4&gt;Sanitize device specification:&lt;/h4&gt;
&lt;p&gt;As part of the initialization process, checks are performed to validate
the correctness of the device specifications. Currently, if duplicates are
present in the specifications, only the first entry is retained. While this
behavior is acceptable, we may consider extending it in the future to log
a warning and notify the user.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="display-management"&gt;
&lt;h4&gt;Display management:&lt;/h4&gt;
&lt;p&gt;From libvirt documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;An optional display attribute may be used to enable using a vgpu device
as a display device for the guest. Supported values are either on or off
(default). There is also an optional ramfb attribute with values of either
on or off (default). When enabled, the ramfb attribute provides a memory
framebuffer device to the guest. This framebuffer allows the vgpu to be used
as a boot display before the gpu driver is loaded within the guest. ramfb
requires the display attribute to be set to on.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;There is a constraint to activate these settings for only one VGPU, even
if multiple VGUs are attached to a VM.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In this initial implementation, display management is out of scope,
consistent with the existing mdev implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following example demonstrates device specifications and alias
configurations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;[&lt;/span&gt;pci&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;device_spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vendor_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10de"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"25b6"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:25:00.4"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;managed:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vendor_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10de"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"25b6"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"device_type"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type-VF"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MYVF"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Creating a VM based on the configuration above will include the following
snippet in the XML definition:&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&amp;lt;hostdev&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'subsystem'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pci'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;managed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'no'&lt;/span&gt;&amp;gt;
&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;driver&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'vfio'&lt;/span&gt;/&amp;gt;
&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;source&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;&amp;lt;address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0000'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x25'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x00'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x4'&lt;/span&gt;/&amp;gt;
&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;/source&amp;gt;
&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'hostdev0'&lt;/span&gt;/&amp;gt;
&lt;span class="w"&gt;  &lt;/span&gt;&amp;lt;address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pci'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0000'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x00'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x05'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0'&lt;/span&gt;/&amp;gt;
&amp;lt;/hostdev&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The above example does not apply if users need to support multiple kinds
of VFs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="support-for-multiple-kinds-of-vfs"&gt;
&lt;h4&gt;Support for multiple kinds of VFs:&lt;/h4&gt;
&lt;p&gt;SR-IOV devices, such as GPUs, can be configured to provide VFs with various
characteristics under the same vendor ID and product ID.&lt;/p&gt;
&lt;p&gt;To enable Nova to model this, if you configure the VFs with different
resource allocations, you will need to use separate resource_classes for each.&lt;/p&gt;
&lt;p&gt;This can be achieved by following the steps below:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enable PCI in Placement: This is necessary to track PCI devices with
custom resource classes in the placement service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define Device Specifications: Use a custom resource class to represent
a specific VF type and ensure that the VFs existing on the hypervisor are
matched via the VF’s PCI address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify Type-Specific Flavors: Define flavors with an alias that matches
the vendor, product, and resource class to ensure proper allocation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="device-specification-resource-class"&gt;
&lt;h4&gt;Device specification resource class:&lt;/h4&gt;
&lt;p&gt;This is necessary for users who want to support multiple kinds of VFs,
requiring the “PCI in placement” feature to be enabled.&lt;/p&gt;
&lt;p&gt;The resource class can user defined provided it conforms to the placement,
validation requirements.
While nova will normalize the resource class string to produce a valid
resource class, relying on this is considered bad practice.&lt;/p&gt;
&lt;p&gt;Normalisation is done by making the string upper case, replacing any
consecutive character outside of &lt;cite&gt;[A-Z0-9_]&lt;/cite&gt;  with a single ‘_’, and
prefixing the name with &lt;cite&gt;CUSTOM_&lt;/cite&gt; if not yet prefixed.&lt;/p&gt;
&lt;p&gt;For example, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_&amp;lt;TYPE_OF_VF&amp;gt;&lt;/span&gt;&lt;/code&gt; i.e. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_GOLD_GPU&lt;/span&gt;&lt;/code&gt; would be a
valid resource class.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following example demonstrates device specifications and alias
configurations, utilizing resource classes as part of the “PCI in
placement” feature.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;[&lt;/span&gt;pci&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;device_spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vendor_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10de"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"25b6"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:25:00.4"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resource_class"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_A16_16A"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"managed"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"device_type"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type-VF"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;resource_class:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_A16_16A"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A16_16A"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Only the existing extra_info free dict will be extended.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;If PCI in placement is enabled, this &lt;a class="reference external" href="https://bugs.launchpad.net/placement/+bug/2070257"&gt;bug&lt;/a&gt; should be taken into account
as it may impact performance.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/q/topic:%22bug/2070257%22"&gt;Mitigation measures&lt;/a&gt; are currently being developed to minimize this impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The user is fully responsible for configuring the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Host device: Define the kinds of virtual VFs required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute Node: Configure device specifications, including whether the
device/driver supports managed=true, along with the necessary aliases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flavors:  If multiple kinds of VFs are needed, users must create and use
different flavors for each VF type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Users with Nvidia virtual GPUs must review their configuration.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Uggla (René Ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Main contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Bauzas (Sylvain Bauza)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Parse managed parameter from PCI device specification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sanitize device specification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change XML generation to deal with managed parameter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit tests + functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Performance impact bug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PCI in placement features for multiple kinds of VFs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit tests and functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest and/or whitebox tests cannot be executed in CI due to hardware
limitations. They can, however, be developed in parallel with this
implementation and deferred for later inclusion in CI.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id6"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>Image properties in server show</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/image-properties-in-server-show.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/image-properties-in-server-show"&gt;https://blueprints.launchpad.net/nova/+spec/image-properties-in-server-show&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes to show an instance’s embedded image properties in the
server show API. This has lots of uses, but is particularly required for &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/936775"&gt;vTPM
live migration&lt;/a&gt;
to show users the vTPM secret security level that is set on their instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova copies the properties of the image into the instance system metadata at
instance create and rebuild to keep this information available even if the
image is changed or deleted later in glance. However the nova API does not
return this authoritative information to the user. As image properties
can affect how the instance is scheduled and what features are enabled for it
in the hypervisor this information is very useful for the user.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;I as the owner of the VM would like to know the image properties used by
nova when scheduling and building my VM even after the image is changed or
deleted in glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Especially I as the owner of an existing VM want to see the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; in the embedded image properties so that I can
observe the default vTPM security mode applied to of my VM before I consent
to such security change. See &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/936775"&gt;vTPM live migration&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I as the owner of the VM want to detect if the admin needed to change
any image properties in my behalf via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-mange&lt;/span&gt; &lt;span class="pre"&gt;image_property&lt;/span&gt; &lt;span class="pre"&gt;set&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In a new API microversion return the embedded image properties in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/server/details&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/server/{server_id}&lt;/span&gt;&lt;/code&gt; and the rebuild case of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/server/{server_id}/action&lt;/span&gt;&lt;/code&gt; responses.&lt;/p&gt;
&lt;p&gt;The implementation needs to populate this part of the api response from our
cache of the image details in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance.system_metadata&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Implement separate top level fields for each feature depending on an image
properties.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;No impact as the image properties are already modelled and persisted today.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;In a new microversion the following API responses are extended:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/server/details&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/server/{server_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/server/{server_id}&lt;/span&gt;&lt;/code&gt; where the action is rebuild&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;properties&lt;/span&gt;&lt;/code&gt; subkey will be added under the struct at the existing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key as a dict where both the keys and the values are following the
schema &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;^[a-zA-Z0-9-_:.&lt;/span&gt; &lt;span class="pre"&gt;]{1,255}$&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The new subkey will be included in the response with the current default
policy of these APIs, which is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROJECT_READER_OR_ADMIN&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Response example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"65fc9d2f-1d02-4bb0-8602-b505252b17f8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"vm1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ACTIVE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
      &lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"197c0527-f0f8-4f94-9ccc-82759bf0dc21"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s2"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"hw_machine_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pc-q35-8.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"hw_vtpm_secret_security"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"hw_tpm_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"hw_tpm_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"tpm-crb"&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"locked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None, the system_metadata is already loaded from the DB when the API response
is generated &lt;a class="reference external" href="https://github.com/openstack/nova/blob/a459467899d2b406aa8cf530ae481255eaf3c957/nova/api/openstack/compute/servers.py#L317-L318"&gt;since microversion 2.73&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;?&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;In a new API microversion extend the API response&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API sample functional test&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API ref&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>libvirt SPICE direct consoles</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/libvirt-spice-direct-consoles.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-spice-direct-consoles"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-spice-direct-consoles&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes modifications to Nova’s libvirt driver to support
“direct” SPICE VDI consoles. These consoles are “direct” in that they are not
intended to use a HTML5 transcoding proxy to access, and instead the user would
use a native SPICE client like &lt;cite&gt;remote-viewer&lt;/cite&gt;. Such a facility enables a much
richer virtual desktop experience that Nova current supports, in return for
relatively minor changes to Nova. A new Nova API microversion is also required
to add this new console type.&lt;/p&gt;
&lt;p&gt;While exposing the SPICE TCP ports on the hypervisor to the internet is not
advisable, this facility allows a SPICE protocol native proxy to channel
traffic from users to the correct hypervisor ports. In order to ensure that the
hypervisor port information is protected, it is only exposed in the API to
callers with admin permissions.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The SPICE protocol was added to Nova a long time ago, and still represents the
richest and most performant option for remote desktops using Nova. However at
the moment, Novas’s HTML5 transcoding proxy is the only way to access these
SPICE consoles, and the HTML5 interface does not support many of the more novel
features of the SPICE protocol, nor does it support high resolution desktops
well.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;As a developer, I don’t want these changes to make the Nova codebase even more
complicated.&lt;/em&gt; The changes proposed are relatively contained – a single new API
microversion, two additional extra specs (for sound and USB passthrough) with
associated domain XML generation code, and associated tests.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As a deployer, I want to be able to use OpenStack to provide rich virtual
desktops to my users.&lt;/em&gt; This change facilitates such functionality, but does
require additional deployment steps such as setup to TLS certificates for your
hypervisors and management of a SPICE native proxy. There is a sample
implementation using Kolla-Ansible available, but other deployment systems
would need to integrate this functionality for it to be generally available.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As a deployer who doesn’t want rich desktop consoles, I don’t want this
functionality to complicate my deployment.&lt;/em&gt; When disabled, the changes to
deployments are minor – for example the extra USB passthrough devices and
sound devices in the domain XML are all disabled unless requested by the
relevant extra specs.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As an end user, I would like access to a richer desktop experience than is
currently available.&lt;/em&gt; Once these changes are integrated and a SPICE native
proxy deployed, a further change to either Horizon or Skyline will be required
to orchestrate console access. It is expected the complete end to end
functionality will take several releases to land before a fully seamless
experience is available. Once fully implemented, Horizon and Skyline will be
capable of delivering a &lt;cite&gt;.vv&lt;/cite&gt; configuration file for a specific console to a
client, who will then have seamless access to their virtual desktop. However,
a user will be able to use the &lt;cite&gt;openstack console url show&lt;/cite&gt; command immediately
to create a console session outside of our web clients.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposed solution is relatively simple – add an API microversion which
makes it possible to create a “spice-direct” console, and to lookup connection
details for that console from the API. The new console type and microversion is
required because we need to be able to specify the new console type, which is
an API schema change.&lt;/p&gt;
&lt;p&gt;The response from a &lt;cite&gt;get_spice_console&lt;/cite&gt; or &lt;cite&gt;create&lt;/cite&gt; call which requests a
“spice-direct” console will return a URL derived from
&lt;cite&gt;CONF.spice.spice_direct_proxy_base_url&lt;/cite&gt;, and will include a console access
token. The user would then request this URL, and the SPICE native proxy
would lookup console connection details from nova via the
&lt;cite&gt;/os-console-auth-tokens/&lt;/cite&gt; API. These details would be used to generate a
virt-viewer &lt;cite&gt;.vv`&lt;/cite&gt; configuration file, which the user can then use to access a
proxied SPICE console.&lt;/p&gt;
&lt;p&gt;Because the response from &lt;cite&gt;/os-console-auth-tokens/&lt;/cite&gt; includes the host and port
on the hypervisor that the SPICE console is running on, it is agreed that these
API methods should have restricted accessibility. However, this is a
pre-existing API and this should already be true. This protects sensitive
network configuration information from being provided to less trusted users.&lt;/p&gt;
&lt;p&gt;This specification also covers tweaks the to the libvirt domain XML to enrich
the desktop experience provided by such a direct console, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;USB device passthrough from client to guest via extra spec configurable
usbredir support (WIP implementation at
I791b16c5bf0e860a188783c863e95dc423998b0a)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sound support via an extra spec to specify a sound device (WIP implementation
at I2faeda0fd0fb9c8894d69558a1ccaab8da9f6a1b)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that allowing concurrent console access from more than one user is
technically feasbile, but forbidden by Nova’s policy of not manipulating the
&lt;cite&gt;qemu`&lt;/cite&gt; command line directly. See I65f94771abdc1a6ef54637ea81f25ce1daaf4963
for discussion on that issue.&lt;/p&gt;
&lt;p&gt;The proposed changes allow direct connection to a SPICE console from a SPICE
native client like &lt;cite&gt;remote-viewer&lt;/cite&gt;. Without additional software, this implies
that such a client would have network connectivity to relatively arbitrary TCP
ports on the hypervisor hosting the instance. However, a SPICE protocol native
proxy now exists, and a parallel proposal to this one proposes adding support
for it to Kolla-Ansible. This proxy is called Kerbside, and more details are
available at &lt;a class="reference external" href="https://github.com/shakenfist/kerbside"&gt;https://github.com/shakenfist/kerbside&lt;/a&gt;. That is, with the proxy
deployed there is effectively no change to the network exposure of Nova
hypervisors.&lt;/p&gt;
&lt;p&gt;When implemented, a user can fetch a Kerbside connection URL like this:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;`&lt;/span&gt;
&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;console&lt;/span&gt; &lt;span class="pre"&gt;url&lt;/span&gt; &lt;span class="pre"&gt;show&lt;/span&gt; &lt;span class="pre"&gt;--spice-direct&lt;/span&gt; &lt;span class="pre"&gt;52b2e44e-e561-464c-88f3-2fc6a1ecea2b&lt;/span&gt;
&lt;span class="pre"&gt;+----------+------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;Field&lt;/span&gt;    &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;Value&lt;/span&gt;                                                            &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;+----------+------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;protocol&lt;/span&gt; &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;spice&lt;/span&gt;                                                            &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;type&lt;/span&gt;     &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;spice-direct&lt;/span&gt;                                                     &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;url&lt;/span&gt;      &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;http://127.0.0.1:13002/nova?token=bf2e6883-...&lt;/span&gt;                   &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;+----------+------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="pre"&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The user then fetches that URL, and Kerbside delivers a &lt;cite&gt;.vv`&lt;/cite&gt; file with the
connection information for a SPICE client. Kerbside uses a call to
&lt;cite&gt;/os-console-auth-tokens/bf2e6883-…&lt;/cite&gt; to determine the validity of the
console authentication token, and the connection information for the console.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Unfortunately the SPICE HTML5 proxy does not meet the needs to many remote
desktop users. Realistically OpenStack does not currently have a way of
providing these rich desktop consoles to users. Instead, other systems such as
Citrix are used for this functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The console auth token table needs to have an extra column added so that TLS
ports can be tracked alongside unencrypted ports. This change is minor and
should not be difficult for deployers to support as this table should not be
particularly large given authentication tokens already expire.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This specification adds a new console type, “spice-direct”, which provides
the connection information required to talk the native SPICE protocol
directly to qemu on the hypervisor. This is intended to be fronted
by a proxy which will handle authentication separately.&lt;/p&gt;
&lt;p&gt;A new microversion is introduced which adds the type “spice-direct”
to the existing “spice” protocol.&lt;/p&gt;
&lt;p&gt;This implies that the JSON schema for &lt;cite&gt;create&lt;/cite&gt; console call would change to
something like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;create_v297&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'remote_console'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'protocol'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'vnc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rdp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'serial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mks'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'novnc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'xvpvnc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spice-html5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="s1"&gt;'spice-direct'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'serial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'webmks'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'protocol'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'remote_console'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And that the JSON schema for the &lt;cite&gt;get_spice_console&lt;/cite&gt; would change to
something like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;get_spice_console_v297&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'os-getSPICEConsole'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'spice-html5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spice-direct'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'os-getSPICEConsole'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response from &lt;cite&gt;/os-console-auth-tokens/&lt;/cite&gt; also needs to be tweaked to return
a TLS port if one is configured for the console, which will require a response
schema change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This proposal has a medium security impact. While hypervisor host / port
details will only be exposed to requestors that have the &lt;cite&gt;service&lt;/cite&gt; role or
&lt;cite&gt;admin&lt;/cite&gt; permissions, Kerbside does need to have network connectivity to the
SPICE TCP ports on the hypervisors in the cloud. However, Kerbside provides a
protective layer to these TCP ports, and it is not intended to expose this
information to less privileged requestors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As discussed, a complete implementation requires deployment systems to
integrate the Kerbside SPICE proxy, as well as modifications to front ends
such as Horizon and Skyline to orchestrate consoles via Kerbside. However,
those are outside the scope of a Nova specification.&lt;/p&gt;
&lt;p&gt;The following configuration options are added by the proposed changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;spice.spice_direct_proxy_base_url&lt;/cite&gt;: defaults to an example URL which
wouldn’t actually work for a non-trivial installation (just as the HTML5
transcoding proxy does). This is the base URL for the Kerbside URLs handed
out by Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;spice.require_secure&lt;/cite&gt;: defaults to &lt;cite&gt;False&lt;/cite&gt;, the current hard coded
default. Whether to require secure TLS connections to SPICE consoles. If
you’re providing direct access to SPICE consoles instead of using the
HTML5 proxy, you may wish those connections to be encrypted. If so, set
this value to True. Note that use of secure consoles requires that you
setup TLS certificates on each hypervisor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following additional image properties will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;hw_audio_model&lt;/cite&gt;: defaults to &lt;cite&gt;None&lt;/cite&gt;, the current hard coded
default. Whether to include a sound device for instance when SPICE
consoles are enabled, and if so what type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;hw_usb_model&lt;/cite&gt;: defaults to &lt;cite&gt;None&lt;/cite&gt;, the current hard coded default. This is
required if &lt;cite&gt;hw_redirected_usb_ports&lt;/cite&gt; is to be configured.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;hw_redirected_usb_ports&lt;/cite&gt;: defaults to &lt;cite&gt;None&lt;/cite&gt;, the current hard coded
default. If configured, this specifies the number of &lt;cite&gt;usbredir&lt;/cite&gt; devices
created within the instance domain XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mikal&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Liaison needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;All code is currently proposed for review in Gerrit.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Testing graphical user interfaces in the gate is hard. However, a test for the
API microversion will be added, and manual testing of the console functionality
has occurred on the prototype and will be redone as the patches land.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The Operators Guide will need to be updated to cover the new functionality and
configuration options. The End User’s guide will need to be updated to
explain usage once the functionality is fully integrated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated and reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result operators need to ensure that Manila
backend storage is routable from the guest subnets.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not be covered
by this spec, any requests to cold migrate evacuate, live migrate rebuild,
resize, shelve, suspend, or volume snapshot an instance with a share attached
will be rejected with a HTTP409 response for the time being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
as it is now &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;supported by libvirt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.
(ref: &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user documentation&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Two new compute capability traits and filters will be introduced to model an
individual compute’s support for virtio-fs and file backed memory.
And while associating a share to an instance, a check will ensure the host
running the instance will support the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and either the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;that the instance is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;From an operator’s point of view, it means
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; support requires that
operators must upgrade all their compute nodes to the version supporting
shares using virtiofs.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; support requires that operators configure one or
more hosts with file backed memory. Ensuring the instance will land on one of
these hosts can be achieved by creating an AZ englobing these hosts.
And then instruct users to deploy their instances in this AZ.
Alternatively, operators can guide the scheduler to choose a suitable host
by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_MEM_BACKING_FILE=required&lt;/span&gt;&lt;/code&gt; as an extra spec or
image property.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the users with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;p&gt;Share mapping status:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                     &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;   &lt;span class="n"&gt;Reboot&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
    &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;--------------+&lt;/span&gt;
    &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;mounted&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;active&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;umount&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;error&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+-------------+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;detaching&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;φ&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Attach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;unmounted&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="n"&gt;v&lt;/span&gt;                                 &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+--------------&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="n"&gt;attaching&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inactive&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;φ means no entry in the database. No association between a share and a server.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Attach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means POST /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Detach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means DELETE /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This chart describe the share mapping status (nova), this is independent from
the status of the Manila share.&lt;/p&gt;
&lt;p&gt;Share attachment/detachment can only be done if the VM state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The operation to start a VM might fail if the attachment of an
underlying share fails or if the share is not in an inactive state.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In such scenarios, the instance will be marked as ERROR. Subsequent
attempts to start the VM will necessitate a hard reboot by the user,
in line with standard procedures for such kind of situations. This
error handling will be centralized and managed by the compute host.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Mount operation will be done when the share is not mounted on the compute host.
If a previous share would have been mounted on the compute host for another
server, then it will attempt to mount it and a warning will be logged that
the share was already mounted.&lt;/p&gt;
&lt;p&gt;Umount operation will be really done when the share is mounted and not used
anymore by another server.&lt;/p&gt;
&lt;p&gt;With the above mount and umount operation, the state is stored in memory and
do not require a lookup in the database.&lt;/p&gt;
&lt;p&gt;The share will be mounted on the compute host using read/write mode.
Read-only will not be supported as a share could not be mounted read-only
and read/write at the same time. If the user wants to mount the share
read-only, it will have to do it in the VM fstab.&lt;/p&gt;
&lt;p&gt;Instance Deletion Processes:&lt;/p&gt;
&lt;p&gt;Standard Deletion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;During a normal deletion process on the compute side, both the unmount
and Manila policy removal are attempted.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If both operations succeed, the corresponding share mapping is also
removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If either the unmount or policy removal fails, the instance
itself is deleted, but a share mapping record may remain in the database.
A future enhancement will include a periodic task designed to unmount,
remove the policy, and clean up any leaked share mappings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Local Deletion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the VM is marked as DELETED in the database due to unavailable
compute during the delete request, no unmounting or Manila policy removal
occurs via the API.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Once the compute is operational again, it identifies instances marked
as DELETED that have not yet been cleaned up. During the initialization
of the instance, the compute attempts to complete the deletion process,
which includes unmounting the share and removing the access policy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If these actions are successful, the share mapping will be removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If either action fails, the deletion remains incomplete; however, the
compute’s startup process continues unaffected, and the error is merely
logged. For security reasons, it’s crucial not to retain the mount,
necessitating a retry mechanism for cleanup. This situation parallels
the standard deletion scenario and requires a similar periodic task
for resolution.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Manila share removal issue:&lt;/p&gt;
&lt;p&gt;An issue was identified in the Zed cycle, a share being used by instances
could be removed by the user.
As a result, the instances would loose access to the data and might cause
difficulties in removing the missing share and fixing the instance.&lt;/p&gt;
&lt;p&gt;A solution was identified with the Manila team to attach metadata to the share
access policy that will lock the share and prevent its deletion until
the lock is not removed.&lt;/p&gt;
&lt;p&gt;This solution was implemented in the Antelope cycle.
The proposal here will use the lock mechanism in Nova.&lt;/p&gt;
&lt;p&gt;Instance metadata:&lt;/p&gt;
&lt;p&gt;Add instance shares in the instance metadata.
Extend DeviceMetadata with ShareMetadata object containing &lt;cite&gt;share_id&lt;/cite&gt; and
&lt;cite&gt;tag&lt;/cite&gt; used to mount the virtiofs on an instance by the user.
See &lt;a class="reference internal" href="#epoxy-other-end-user-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{share_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PROJECT_ADMIN will be able to see details of the attachment id and export
location stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance must be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance should have the required capabilities to enable
virtiofs (see above).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This API operates asynchronously. Consequently, the share_mapping is defined
and it status is marked as “attaching” in the database.&lt;/p&gt;
&lt;p&gt;In the background, the compute node will request Manila to grant access to
the share and lock it for nova usage. Once this process is complete, the
share status is changed to inactive.  It’s important to note that locking
the share also restricts visibility to users to prevent any inadvertent
exposure of internal data.&lt;/p&gt;
&lt;p&gt;Following that, when the VM is powered on, the share will be mounted
onto the compute node and designated as active provided there are no
errors. Conversely, when the VM is powered off, the share will be unmounted
from the compute node and marked as inactive, again, if there are no errors
encountered.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter in the request body, when not
provided it will be the share_id(UUID) as always provided in the request.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; if povided by the user must be an ASCII string with a maximum
lenght of 64 bytes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{share_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance must be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;This API functions asynchronously, leading to the share_mapping status being
marked as detaching.&lt;/p&gt;
&lt;p&gt;Concurrently, the compute system conducts a verification to see if the
share is no longer being utilized by another instance. If found unused,
it requests Manila to unlock the share and deny access.&lt;/p&gt;
&lt;p&gt;To maintain consistent logic for both NFS and CephFS, we currently remove
the access policy only after the last user has unmounted the share across
all compute systems. While NFS could potentially implement an access policy
based on per-compute IP, CephFS currently employs an access token specific to
each Nova user. In the future, we may explore utilizing a CephFS user/token
that is specific to each Nova instance on each compute system.&lt;/p&gt;
&lt;p&gt;Two checks are necessary:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To unmount, it’s important to verify whether any other virtual machines
are using the share on the same compute system. This mechanism is already
implemented by the driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For removing the access policy, we need to
ensure that no compute system is currently using the share.
Once this process is finalized, the association of the share is eliminated
from the database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Primary key autoincrement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attaching&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detaching&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inactive&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within
the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the
underlying host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_proto&lt;/span&gt;&lt;/code&gt; - The Shared File Systems protocol (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NFS&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CEPHFS&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;The database field &lt;cite&gt;status&lt;/cite&gt; and &lt;cite&gt;share_proto&lt;/cite&gt; values will not be enforced
using enums allowing future changes and avoid database migrations.
However, to make code more robust, enums will be defined on the object fields.&lt;/p&gt;
&lt;p&gt;Fields containing text will use String and not Text type in the database schema
to limit the column width and be stored inline in the database.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to mount the
share to the host and the host filesystem location should
not be logged by Nova and only accessible by default through the API by admins.&lt;/p&gt;
&lt;p&gt;This &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; field will also be excluded from notifications by
choice.&lt;/p&gt;
&lt;p&gt;The Nova abstraction with the Openstack SDK needs to be updated so that, when
a user requests Nova to attach a Manila share to their instance, Nova utilizes
the user’s Keystone token when communicating with Manila. This ensures that
Manila can properly verify the user’s access to the requested share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One to add new notifications for share attach and share detach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One to extend the instance update notification with the share mapping
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Share mapping in the instance payload will be optional and controlled via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include_share_mapping&lt;/span&gt;&lt;/code&gt; notification configuration parameter. It will be
disabled by default.&lt;/p&gt;
&lt;p&gt;Proposed payload for attached and detached notification will be the same as
the one returned by the show command with admin rights.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Proposed instance payload for instance updade, will be the list of share
attached to this instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"share_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7987"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="epoxy-other-end-user-impact"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Users could use the instance metadata to discover and auto mount the share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.
While there will be near local performance between the vm and host,
the actual performance will be limited by the network performance of
the network file share protocol and hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and capability traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;p&gt;A new DB migration constraint to prevent a share to be attached more
than once will be introduced.
Because the share_mapping table was never able to be utilized in production,
it is proposed that the table be dropped and then reconstructed with the
updated constraint. This approach will help standardize the process across
all database systems, as sqlite does not allow altering table constraints,
requiring the table to be recreated.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (initial contributor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new capability traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated and reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated and reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>Live migrate VFIO devices using kernel variant drivers</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/migrate-vfio-devices-using-kernel-variant-drivers.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/migrate-vfio-devices-using-kernel-variant-drivers"&gt;https://blueprints.launchpad.net/nova/+spec/migrate-vfio-devices-using-kernel-variant-drivers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the necessary steps to live migrate SR-IOV devices
using the new kernel VFIO SR-IOV variant driver interface.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Support for devices using the variant driver interface is detailed in this
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/enable-vfio-devices-with-kernel-variant-drivers.html"&gt;specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, the migration process is not covered there.
This is addressed in the following section, which describes the Nova updates
required  for SRIOV devices using VFIO SR-IOV variant driver to be live
migrated to other hosts supporting the same devices.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to live migrate VMs with SR-IOV devices if such
operation is supported by the variant driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to declare whether a device is live migratable or
non-live migratable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to define flavors that use live migratable or
non-live migratable devices.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="description"&gt;
&lt;h3&gt;Description:&lt;/h3&gt;
&lt;section id="configuring-pci-device-specification"&gt;
&lt;h4&gt;Configuring PCI device specification:&lt;/h4&gt;
&lt;p&gt;Administrator must specify whether the device is eligible for live migration to
a similar device on another compute node.&lt;/p&gt;
&lt;p&gt;The proposed solution is to add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable&lt;/span&gt;&lt;/code&gt; tag to the device
specification in [pci]dev_spec config.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable='yes'&lt;/span&gt;&lt;/code&gt; means that the device can be live migrated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable='no'&lt;/span&gt;&lt;/code&gt; means that the device cannot be live migrated.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When this tag is encountered by the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/f98f414f971b6c897bf48781a579730419b5a93d/nova/compute/pci_placement_translator.py#L597-L600"&gt;PCI resource tracker&lt;/a&gt;, the
corresponding information will be stored in the respective PciDevice
object under the extra_info field.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If not specified, the default behavior will be equivalent to
live_migratable=’no’. However, this value will not be persisted in the
PciDevice object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The PciDevice object version remains unchanged.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Additionally, if pci in placement is enabled and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable='yes'&lt;/span&gt;&lt;/code&gt;,
it will record a new standard trait, HW_PCI_LIVE_MIGRATABLE, in the resource
provider representing the physical device. While this trait will not be
utilized by the migration flow, it can serve as a reference for inventory
and later the PCI in Placement code path can be extended to automatically
request this trait if the PCI alias requests &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable=yes&lt;/span&gt;&lt;/code&gt; device(s).&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since this is not mandatory for the migration, it will be included in
separate commits.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="configuring-pci-aliases"&gt;
&lt;h4&gt;Configuring PCI aliases:&lt;/h4&gt;
&lt;p&gt;Users must specify whether the PCI request, and consequently the flavor,
requires a live migratable device.&lt;/p&gt;
&lt;p&gt;The proposed solution is to add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable&lt;/span&gt;&lt;/code&gt; key to the PCI alias
definition in the [pci]alias config.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable='yes'&lt;/span&gt;&lt;/code&gt; means that the user wants a device(s) allowing live
migration to a similar device(s) on another host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable='no'&lt;/span&gt;&lt;/code&gt; This explicitly indicates that the user requires a
non-live migratable device, making migration impossible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If not specified, the default is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;live_migratable=None&lt;/span&gt;&lt;/code&gt;, meaning that
either a live migratable or non-live migratable device will be picked
automatically. However, in such cases, migration will &lt;strong&gt;not&lt;/strong&gt; be possible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="live-migration-modifications"&gt;
&lt;h4&gt;Live migration modifications:&lt;/h4&gt;
&lt;p&gt;Verify in _check_can_migrate_pci() whether the source instance contains
live migratable devices. If no live migratable devices are found, raise an
exception indicating that the migration is not possible.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The VM on the source host might have PCI devices attached that are not
related to any PCI alias, but it is there because of neutron direct or
direct-physical ports. In this case nova should do what it does today,
detach these ports at the start of the migration and re-attach them on the
dest after the migration. Also such PCI devices having no live_migratable=yes
key in their extra_info should not prevent the live migration to be accepted.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Modify stats.py in the filter_pools() function to handle PCI requests for
live_migratable devices. Ensure it retrieves hosts with the appropriate number
of live migratable devices by adding a new filter.&lt;/p&gt;
&lt;p&gt;Since VIF field is not used in this context, we need to claim PCI devices and
retrieve the PCI addresses of the destination host.&lt;/p&gt;
&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LiveMigrateData&lt;/span&gt;&lt;/code&gt; object to include the PCI device mapping
between the source and destination device addresses. A new field,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_dev_map_src_dst&lt;/span&gt;&lt;/code&gt;, defined as a  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DictOfStringsField&lt;/span&gt;&lt;/code&gt; will
be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LiveMigrateData&lt;/span&gt;&lt;/code&gt; object for this purpose.&lt;/p&gt;
&lt;p&gt;Update the _live_migration_operation() function, with a specific
focus on the get_updated_guest_xml() function, to map the source PCI
addresses to the destination addresses in the destination XML file
using the data provided by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LiveMigrateData&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If PCI in Placement is enabled then live migration will work as today
for neutron requested PCI devices (i.e. legacy behavior works)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If PCI in Placement is enabled then SR-IOV live migration proposed in
this spec will still work (i.e. new functionality works)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optionally PCI in Placement will be extended to automatically request
HW_PCI_LIVE_MIGRATABLE trait if the alias has live_migratable=”yes”.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A further enhancement would be to extend the translation of the
[pci]alias spec to placement RequestGroups to support forbidden traits.
So when live_migratable=no is present in the alias the
HW_PCI_LIVE_MIGRATABLE trait is requested as forbidden.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;For NICs such as the Mellanox ConnectX-7, if both live_migrate=yes and
physical_network=”label” are set, the migration mechanism defined in this
specification will be used instead of the legacy one.&lt;/p&gt;
&lt;p&gt;However, this change will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Be implemented in a separate patch to allow the base case to land first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that such NICs are properly live migrated using the new code path.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://github.com/openstack/nova/blob/b27447d55dbe6660eae7283ff7c32259d31967c7/nova/pci/request.py#L72-L117"&gt;schema definition for PCI aliases&lt;/a&gt; needs to be modified to allow the
specification of live migratable devices.&lt;/p&gt;
&lt;p&gt;However, this change should not require a microversion bump.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;LiveMigrateDate object will be extended to supply the PCI devices info
of the destination host introducing a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_devices&lt;/span&gt;&lt;/code&gt; field.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;If PCI in placement is enabled, this &lt;a class="reference external" href="https://bugs.launchpad.net/placement/+bug/2070257"&gt;bug&lt;/a&gt; should be taken into account
as it may impact performance.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/q/topic:%22bug/2070257%22"&gt;Mitigation measures&lt;/a&gt; are currently being developed to minimize this impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The user is fully responsible for configuring the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Device specifications and aliases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flavors: If users need to support multiple kinds of
VFs, they must use different flavors for each VF type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;All VMs with devices that rely on the VFIO SR-IOV variant driver cannot
be migrated until they use a new flavor that includes the correct updated
aliases pointing to the revised PCI device specifications.&lt;/p&gt;
&lt;p&gt;This can be achieved by resizing the VM and changing its flavor to the new one.&lt;/p&gt;
&lt;p&gt;For NICs, an alternative approach could be to detach and reattach the device.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Uggla (René Ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Main contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Bauzas (Sylvain Bauza)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Parse live_migratable from [pci]dev_spec config.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add HW_PCI_LIVE_MIGRATABLE trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check source instance for appropriate live migratable devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new filter in filter_pools to manage live migratable devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update LiveMigrateData to include PCI device information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update get_updated_guest_xml() function to include PCI device information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Support for devices using the variant driver interface.
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/enable-vfio-devices-with-kernel-variant-drivers.html"&gt;specification&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance impact bug.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit tests and functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest and/or whitebox tests cannot be executed in CI due to hardware
limitations. They can, however, be developed in parallel with this
implementation and deferred for later inclusion in CI.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>OpenAPI Schemas</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/openapi.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/openapi-2"&gt;https://blueprints.launchpad.net/nova/+spec/openapi-2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to start documenting our APIs in an industry-standard,
machine-readable manner. Doing so opens up many opportunities for both
OpenStack developer and OpenStack users alike, notably the ability to both
auto-generate and auto-validate both client tooling and documentation alike. Of
the many API description languages available, OpenAPI (fka “Swagger”) appears
to be the one with both the largest developer mindshare and the one that would
be the best fit for OpenStack due to the existing tooling used in many
OpenStack services, thus we would opt to use this format.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is a continuation of a spec that was previously approved in Dalmatian
(2024.2). We merged all of the groundwork for this in Dalmatian but did not
get the response bodies schemas merged.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The history of API description languages has been mainly a history of
half-baked ideas, unnecessary complication, and in general lots of failure.
This history has been reflected in OpenStack’s own history of attempting to
document APIs, starting with our early use of WADL through to our experiments
with Swagger 2.0 and RAML, leading to today’s use of our custom &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
project, built on reStructuredText and Sphinx.&lt;/p&gt;
&lt;p&gt;It is only in recent years that things have started to stabilise somewhat, with
the development of widely used API description languages like OpenAPI, RAML and
API Blueprint, as well as supporting SaaS tools such as Postman and Apigee.
OpenAPI in particular has seen broad adoption across multiple sectors, with
sites as varied as &lt;a class="reference external" href="https://blog.cloudflare.com/open-api-transition"&gt;CloudFlare&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/github/rest-api-description"&gt;GitHub&lt;/a&gt; providing OpenAPI schemas for
their APIs. OpenAPI has evolved significantly in recent years and now supports
a wide variety of API patterns including things like webhooks. Even more
beneficial for OpenStack, OpenAPI 3.1 is a full superset of JSON Schema meaning
we have the ability to re-use much of the validation we already have.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an end user, I would like to have access to machine-readable, fully
validated documentation for the APIs I will be interacting with.&lt;/p&gt;
&lt;p&gt;As an end user, I want statically viewable documentation hosted as part of the
existing docs site without requiring a running instance of Nova.&lt;/p&gt;
&lt;p&gt;As an SDK/client developer, I would like to be able to auto-generate bindings
and clients, promoting consistency and minimising the amount of manual work
needed to develop and maintain these.&lt;/p&gt;
&lt;p&gt;As a Nova developer, I would like to have a verified API specification that I
can use should I need to replace the web framework/libraries we use in the
event they are no longer maintained.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This effort can be broken into a number of distinct steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new decorator for removed APIs and actions&lt;/p&gt;
&lt;p&gt;We have a number of APIs and actions that no longer have backing code and
return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;(Bad&lt;/span&gt; &lt;span class="pre"&gt;Request)&lt;/span&gt;&lt;/code&gt;, respectively. We
will not add schemas for these in the initial attempt at this so we need some
mechanism to indicate this. We will add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;removed&lt;/span&gt;&lt;/code&gt; decorator that will
highlight these removed APIs and indicate the version they were removed in
and the reason for their removal. We can later use this as a heuristic in our
tests to skip schema checks for these methods.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This was completed in Dalmatian (2024.2)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing request body and query string schemas&lt;/p&gt;
&lt;p&gt;There is already good coverage of both request bodies and query string
parameters but it is not complete. A list of incomplete schemas is given at
the end of this section. The additional schemas will merely validate what is
already allowed, which will mean extensive use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"additionalProperties":&lt;/span&gt;
&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; or empty schemas. Put another way, an API that currently ignores
unexpected request body fields or query string parameters will continue to
ignore them. We may wish to make these stricter, as we did for most APIs in
microversion 2.75, but that is a separate issue that should be addressed
separately.&lt;/p&gt;
&lt;p&gt;Once these specs are added, tests will be added to ensure all non-deprecated
and non-removed API resources have appropriate schemas.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This was completed in Dalmatian (2024.2)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;
&lt;p&gt;These will be sourced from existing OpenAPI schemas, currently published
at &lt;a class="reference external" href="https://github.com/gtema/openstack-openapi"&gt;github.com/gtema/openstack-openapi&lt;/a&gt;, from &lt;a class="reference external" href="https://github.com/openstack/tempest/tree/c0da6e843a/tempest/lib/api_schema/response/compute"&gt;Tempest’s API schemas&lt;/a&gt;,
and where necessary from new schemas auto-generated from JSON response bodies
generated in tests and manually modified handle things like enum values.&lt;/p&gt;
&lt;p&gt;Once these are added, tests will be added to ensure all non-deprecated and
non-removed API resources have appropriate response body schemas. In
addition, we will add a new configuration option that will control how we do
verification at the API layer, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. This will be an
enum value with three options:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Raise a HTTP 500 (Server Error) in the event that an API returns an
“invalid” response.&lt;/p&gt;
&lt;p&gt;This will be the default in CI i.e. for our unit, functional and
integration tests. This should not be used in production. The help text
of the option will indicate this and we will set the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;advanced&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Log a warning about an “invalid” response, prompting operations to file a
bug report against Nova.&lt;/p&gt;
&lt;p&gt;This will be initial (and likely forever) default in production.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ignore&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Disable API response body validation entirely. This is an escape hatch in
case we mess up.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The development of tooling required to gather these JSON Schema schemas and
generate an OpenAPI schema will not be developed inside Nova and is
therefore not covered by this spec. Nova will merely consume the resulting
tooling for use in documentation. It is intended that the same tool will be
usable across any OpenStack project that uses the same web frameworks
(in Nova’s case, WebOb + Routes).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The impact of middleware that modifies either the request or response will
not be accounted for in this change. This is because these are configurable
and they cannot be guaranteed to exist in a given deployment. Examples
include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sizelimit&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.middlware&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_token&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;keystonemiddleware&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a different tool&lt;/p&gt;
&lt;p&gt;We could use a different tool than OpenAPI to publish our specs. In a manner
of speaking we already do this - albeit not in a machine-readable manner -
through our use of os-api-ref.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because OpenAPI is clearly the best tool for the
It is the most widely used API description language available today and
aligns well with our existing use of JSON Schema for API validation. While it
does not support OpenStack’s microversion API design pattern out-of-the-box,
previous experiments have demonstrated that it is extensible enough to add
this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain these specs out-of-tree&lt;/p&gt;
&lt;p&gt;We could use a separate repo to store and maintain specs for Nova and the
other OpenStack services.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because it prevents us testing the specs on each
commit to Nova and means work that could be spread across multiple teams is
instead focused on one small team. It will result in more bugs and a lag
between changes to the Nova API and changes to the out-of-tree specs. It will
result in duplication of effort across Nova, Tempest, and the specs projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish the spec via an API resource rather than in our docs&lt;/p&gt;
&lt;p&gt;We could publish the spec via a new, unversioned API endpoint such as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/spec&lt;/span&gt;&lt;/code&gt;. A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; request to this would return the full spec, either
statically generated at deployment time or dynamically generated (and then
cached) at runtime.&lt;/p&gt;
&lt;p&gt;This is rejected because it brings limited advantages and multiple
disadvantages. Nova’s API is designed to be backwards-compatible and
non-extensible. As such, a user with the latest version of the spec should be
able to use it to communicate with any OpenStack deployment running a version
of Nova that supports microversions. It is also expected that the “master”
version of the spec will continuously improve as things are tightened up,
documentation is improved, and bugs or mistakes are corrected. We want
consumers of the spec to see these changes immediately rather than wait for
their deployment to be updated. Finally, OpenStack’s previous forays into
discoverable APIs, such as Keystone’s use of JSONHome or Glance’s attempts to
publish resource schemas, have seen limited take-up outside of the projects
themselves. Taken together, this all suggests there is no reason or advantage
to publishing deployment-specific specs and users would be better served by
fetching the latest version of the spec from the api-ref documentation
published on docs.openstack.org (which, one should note, is itself
intentionally unversioned).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no direct REST API impact. Users will see HTTP 500 error if they
set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; and encounter an invalid response,
however, we will not encourage use of this option in production and will
instead focus on validating this ourselves in CI.&lt;/p&gt;
&lt;p&gt;We may wish to address issues that are uncovered as we add schemas, but this
work is considered secondary to this effort and can be tackled separately.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This should be very beneficial for users who are interested in developing
client and bindings for OpenStack. In particular, this should (after an initial
effort in code generation) reduce the workload of the SDK team as well as teams
outside of OpenStack that work on client tooling such as the Gophercloud team.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be a minimal impact on API performance when validation is enabled as
we will now verify both requests and responses for all API resources. Given our
existing extensive use of JSON Schema for API validation, it is expected that
this should not be a significant issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As noted previously, there will be one new config option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. Operators may see increased warnings in their logs due
to incomplete schemas, but most if not all of these issues should be ironed out
by our CI coverage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers working on the API microversions will now be encouraged to provide
JSON Schema schemas for both requests and responses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gtema&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add missing request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add decorator to validate response body schemas against response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The actual generation of an OpenAPI documentation will be achieved via a
separate tool. It is not yet determined if this tool will live inside an
existing project, such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstacksdk&lt;/span&gt;&lt;/code&gt;, or inside a
wholly new project. In any case, it is envisaged that this tool will handle
OpenStack-specific nuances like microversions that don’t map 1:1 to OpenAPI
concepts in a consistent and documented fashion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests will ensure that schemas eventually exist for request bodies, query
strings, and response bodies.&lt;/p&gt;
&lt;p&gt;Unit, functional and integration tests will all work together to ensure that
response body schemas match real responses by setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Initially there should be no impact as we will continue to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
as-is for our &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;api-ref&lt;/span&gt;&lt;/code&gt; docs. Eventually we will replace or extend this
extension to generate documentation from our OpenAPI schema.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;section id="apis-missing-schemas"&gt;
&lt;h3&gt;APIs missing schemas&lt;/h3&gt;
&lt;p&gt;These are the APIs that are currently (as of 2024-04-11, commit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;1bca24aeb&lt;/span&gt;&lt;/code&gt;)
missing API request body schemas and query string schemas.&lt;/p&gt;
&lt;p class="rubric"&gt;Missing request body schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._inject_network_info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._reset_network&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._add_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._remove_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.sync_instances&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._force_delete&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._restore&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.reserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.unreserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LockServerController._unlock&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._associate_host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_host_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_project_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController._disassociate_host_and_project&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.add&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._pause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._unpause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RemoteConsolesController.get_rdp_console&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RescueController._unrescue&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._addSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._removeSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_confirm_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_revert_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._start_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._stop_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve_offload&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._resume&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._suspend&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Missing request query string schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.capacities&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsoleAuthTokensController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorAccessController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPPoolsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.reboot&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.shutdown&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.startup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.search&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.statistics&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.uptime&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaClassSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.defaults&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerDiagnosticsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerPasswordController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerSecurityGroupController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTopologyController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerVirtualInterfaceController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SnapshotController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VersionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We should emphasise that many - but not all - of the aforementioned APIs
are either deprecated or removed. We may wish &lt;em&gt;not&lt;/em&gt; to add schemas for
these, though by doing so we will lose the ability to generate documentation
or clients for these APIs from the OpenAPI spec.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced. Missing query schema and request body schemas added.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish response body schemas.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>Show Scheduler Hints in Server Details</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/show-scheduler-hints-in-server-details.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/show-scheduler-hints-in-server-details"&gt;https://blueprints.launchpad.net/nova/+spec/show-scheduler-hints-in-server-details&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova currently lacks a straightforward way to expose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler&lt;/span&gt; &lt;span class="pre"&gt;hints&lt;/span&gt;&lt;/code&gt;
associated with a server. This proposal suggests extending existing Nova’s
API to allow users to retrieve this information when it is available.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Scheduler hints can be specified at server creation time and can influence
placement decisions based on the user-provided configuration. These hints are
stored in the Nova’s database and can be later considered by the scheduler
during a server migration. Without this information beforehand, an API user
can choose an invalid destination host for a migration request, and face
difficulties to understand the real cause of the failure.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to retrieve more details about a server creation
request, which includes the associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler_hints&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud admin, I want to check more informations associated to all running
servers, including their scheduler hints, in order to build an migration
plan from a host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An optimization service like Watcher &lt;a class="reference external" href="https://docs.openstack.org/watcher/latest/"&gt;[1]&lt;/a&gt; would benefit from additional
placement constraints, like scheduler hints, from all instances of a host
in order to build a more concrete action plan to optimize the workload
balance across the cluster. Without this information, Watcher could propose
a solution that contains lots of server migration actions that violate some
constraints. E.g.: Watcher would not account that a host is an invalid
destination for a server that was created with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;different_host&lt;/span&gt;&lt;/code&gt; scheduler
hint.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;Code changes&lt;/h3&gt;
&lt;p&gt;Extend the API response for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt; to include information about the scheduler hints.&lt;/p&gt;
&lt;p&gt;Add a new entry in the API response with the key &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler_hints&lt;/span&gt;&lt;/code&gt;,
containing all persisted scheduler hints associated with the corresponding
server. The value format will follow the same json schema defined in server
creation request &lt;a class="reference external" href="https://github.com/openstack/nova/blob/master/nova/api/openstack/compute/schemas/servers.py"&gt;[2]&lt;/a&gt;. If a server has no information about scheduler
hints, the value will be set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{}&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Both openstack client and openstack sdk will be updated to support the new API
and display the new field added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="user-driven-instance-metadata"&gt;
&lt;h4&gt;User driven instance metadata&lt;/h4&gt;
&lt;p&gt;Users could aditionally store scheduler hints information in instance
metadata. This would allow them to query this inforamation later when needed.
The drawbacks are that it duplicates this information in nova database and
also requires an additional manual step from user’s side.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The following change will be introduced in a new API microversion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Show Server Details&lt;/p&gt;
&lt;p&gt;Return Code(s): 400, 401, 403 (no changes)&lt;/p&gt;
&lt;p&gt;Proposed JSON response addition:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="s2"&gt;"scheduler_hints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"af16eb84-88fe-4cc4-b558-1752cbe8cb15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"same_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"6605bff6-86b9-4824-b35b-a6b3c4c0e717"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;List Servers Detailed&lt;/p&gt;
&lt;p&gt;Return Code(s): 400, 401, 403 (no changes)&lt;/p&gt;
&lt;p&gt;Proposed JSON response addition:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;...&lt;/span&gt;
            &lt;span class="s2"&gt;"scheduler_hints"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
              &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"dc0ca1ef-7e0b-4cb5-89aa-b2069f8b8a8a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"different_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"6dffb036-d020-4630-b467-334400a050ca"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The default policy of the new field will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_reader_or_admin&lt;/span&gt;&lt;/code&gt;
to match with the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt; policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;A new field with scheduler hints information will be added in the output of
the commands &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Show&lt;/span&gt; &lt;span class="pre"&gt;Server&lt;/span&gt; &lt;span class="pre"&gt;Details&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;List&lt;/span&gt; &lt;span class="pre"&gt;Servers&lt;/span&gt; &lt;span class="pre"&gt;Detailed&lt;/span&gt;&lt;/code&gt;, in both
openstack client and openstack sdk.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dviroel&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new field to the server details response in a new microversion,
and populated it with the persisted scheduler hints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend existing unit and functional tests, including API sample tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend existing scheduler_hints and show server details tempest tests to
validate that the new microversion contains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler_hints&lt;/span&gt;&lt;/code&gt; information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API documentation, including API samples in API Reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update openstack client and openstack sdk to support the new microversion
and to show the new field.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Existing unit, funcional, API sample and tempest tests can be extended to
validate that the new microversion contains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scheduler_hints&lt;/span&gt;&lt;/code&gt; information.
If needed, new tests can be added to properly cover other scenarios.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API Reference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;REST API Version History&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack client and openstack sdk documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Previous spec proposal for this blueprint:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/440580"&gt;https://review.opendev.org/c/openstack/nova-specs/+/440580&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>Config option to control behavior of unset unified limits</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/implemented/unified-limits-nova-unset-limits.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unified-limits-nova-unset-limits"&gt;https://blueprints.launchpad.net/nova/+spec/unified-limits-nova-unset-limits&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The default behavior in the oslo.limit quota enforcement library used by Nova
when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; is to
consider resources that do not have registered limits set as having a limit of
zero. This behavior can be unforgiving especially in the scenario of an
upgrade that enables unified limits quota (i.e. if we ever want to make unified
limits the default). If we make the behavior configurable within Nova, we can
help prevent situations where an admin/operator upgrades or installs Nova and
suddenly all API requests begin to be rejected for being over quota.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The problem is centered around the behavior of the oslo.limit quota enforcement
library when a given resource does not have a registered limit set for it. If
no registered limit is found for a resource, the enforce function will consider
that resource to have a limit of 0 and all requests for the resource will fail
for being over quota.&lt;/p&gt;
&lt;p&gt;We want to be able to change the default quota driver to the
UnifiedLimitsDriver, but the aforementioned behavior raises concerns about
changing the default.&lt;/p&gt;
&lt;p&gt;If we were to make unified limits quotas the default in Nova, any
admin/operator who has missed auditing all of their resources and limits in
Keystone before upgrading could experience complete denial of service by the
Nova API immediately after the upgrade. This could happen if even one resource
is missing a registered limit set in Keystone.&lt;/p&gt;
&lt;p&gt;While ideally an admin/operator will not miss setting any registered limits in
an upgrade scenario like this, the penalty for missing even one resource limit
is quite harsh as the API rejects all requests for that resource leading to an
immediate emergency situation.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator, I would like to be able to control which resources I
will require to have a limit set. And I would also like to be able to control
which resources I do not need any limit set, by not including them in the
required resources list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator, I would like to be able to see a DEBUG log message if I
have missed setting a registered limit for a resource in Keystone, rather
than to have all API requests involving that resource be rejected for being
over quota.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposal in this spec is to add new configuration option(s) to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]&lt;/span&gt;&lt;/code&gt; group which would enable operators to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Require limit enforcement for only specific resources, or&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Require limit enforcement for all resources except specific resources&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal with the options is to make management of unset unified limits easy
and maintainable over time.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Alternatively we could make a change to the oslo.limit library to handle
missing registered limits differently than it does today &lt;a class="reference external" href="https://review.opendev.org/c/openstack/oslo.limit/+/899415"&gt;[1]&lt;/a&gt;. This would be
more difficult because oslo.limit 1) has established and thus expected default
behavior and 2) providing new behavior that fits all OpenStack projects may not
be realistic.&lt;/p&gt;
&lt;p&gt;A previously proposed alternative would be a boolean config option
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; which has only two modes: consider unset
limits as zero or consider unset limits as unlimited &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/923807/3/specs/2024.2/approved/unified-limits-nova-unset-limits.rst"&gt;[2]&lt;/a&gt;. Discussion at the
last PTG raised concerns that a boolean option is likely too generic and
wouldn’t provide the level of control most operators would need.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;If a resource is not configured to require limit enforcement, that resource
would be considered to have unlimited quota and malicious callers could attempt
to exhaust that resource intentionally.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The performance impact of using new config options to handle unset limits
should be relatively small as it will add one extra Keystone API call each time
1) a quota check fails and 2) the limit for the associated resource is returned
as 0 by oslo.limit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Admin/operators will need to consider if and when they will need to adjust
configuration values if new Placement resource classes are added to their
deployment in the future.&lt;/p&gt;
&lt;p&gt;Also as part of this work, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt; &lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt;
CLI command will be enhanced to scan the database for resources in flavors that
do not have registered limits set and show them in the output. The intent is to
help admins/operators catch all resources and set limits for them before
unified limits quotas are enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;There should not be upgrade impact with the new configuration options.&lt;/p&gt;
&lt;p&gt;For a deployer not running with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;, the config options have no
effect.&lt;/p&gt;
&lt;p&gt;For a deployer already running with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;, they will have had to set
registered limits for all resources allocated by their cloud (because the
current behavior is to default all limits to zero) and should not experience
any change in quota enforcement for those resources.&lt;/p&gt;
&lt;p&gt;After upgrading however, any _new_ resource the deployer adds to the cloud will
either default to unlimited quota or default to zero quota until the deployer
sets a registered limit for it in Keystone, depending on how the deployer has
configured the new options. If the deployer needs to update config option
values, they need to update them for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-api&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-conductor&lt;/span&gt;&lt;/code&gt;
services. Quota “rechecks” are performed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-conductor&lt;/span&gt;&lt;/code&gt; service if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]recheck_quota&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; (the default).&lt;/p&gt;
&lt;p&gt;For a deployer switching to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; during the upgrade, the
default behavior will only require limits for the default resources in the
config options (currently proposed as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;It is recommended for these deployers to first use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt;
&lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt; tool to have it read their legacy quota limits from
the Nova database and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]&lt;/span&gt;&lt;/code&gt; config options and set them in
Keystone automatically. The output of the command will also show what
resources, if any, are found to be used in the deployment but do not have
registered limits set in Keystone. Deployers can use this information to know
what resources they need to set limits for in Keystone.&lt;/p&gt;
&lt;p&gt;Then, deployers should add or remove resources from the list based on the
resources they want to require to enforce quota. All other resources will be
considered to have unlimited quota until the deployer sets registered limits
for them in Keystone.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add configuration options to control which resources to require a registered
limit set in Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Augment the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt; &lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt; command to scan
database flavors to detect resources that do not have registered limits set
and show them in the output to the user to let them know which limits they
need to set&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Related to &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The functionality of the new config options will be tested by writing new
functional tests. Adding testing to the post test hook for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-next&lt;/span&gt;&lt;/code&gt; CI
job is also a possibility.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/unified-limits.html"&gt;unified limits documentation&lt;/a&gt; will be updated to include information
about the new config options.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/unified-limits.html"&gt;https://docs.openstack.org/nova/latest/admin/unified-limits.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.limit/latest/user/usage.html"&gt;https://docs.openstack.org/oslo.limit/latest/user/usage.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed with changes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 11 Mar 2025 00:00:00 </pubDate></item><item><title>Search flavors by name</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/approved/flavor-search-by-name.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/flavor-search-by-name"&gt;https://blueprints.launchpad.net/nova/+spec/flavor-search-by-name&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow users to search for flavor by name server-side.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, there is no mechanism to filter flavors by flavor name using the
API. Instead, you must retrieve all flavors and filter manually. This can be
expensive, particularly when “flavor explosion” is taken into account. We would
like to resolve this by adding support for a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; filter.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a developer of client tooling, I would like to do as much filtering
server-side as possible, in order to improve performance and reduce
unnecessary network traffic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt; API to add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; query string
filter parameter. This will support regex-style syntax, similar to many other
existing APIs such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;. As with those APIs, this will default
to partial matches and a regular expression must be used to get exact matches.
For example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;openstack&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openstack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'devstack'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/flavors'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'/flavors'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'flavors'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="go"&gt;['m1.small', 'ci.m1.small', 'm1.medium', 'ci.m1.medium', 'm2.small', 'ds512M', 'ds1G']&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'/flavors?name=m1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'flavors'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="go"&gt;['m1.small', 'ci.m1.small', 'm1.medium', 'ci.m1.medium']&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'/flavors?name=^m1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s1"&gt;'flavors'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="go"&gt;['m1.small', 'm1.medium']&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will be implemented by reusing the logic currently used for instances in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_regex_instance_filter&lt;/span&gt;&lt;/code&gt;, seen &lt;a class="reference external" href="https://github.com/openstack/nova/blob/41773f8c6515021eb037e6d9d385b34e89191c8c/nova/db/main/api.py#L1999-L2028"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While we are introducing a new microversion, we will also take the opportunity
to address some other tech debt with the schema:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We will set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; for the flavor show (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/flavors/{flavor_id}&lt;/span&gt;&lt;/code&gt;) API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; field from the flavor create (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;
&lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt;), flavor list with details (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/detail&lt;/span&gt;&lt;/code&gt;) and flavor
show (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/{flavor_id}&lt;/span&gt;&lt;/code&gt;) APIs. We will also remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt;
from the list of valid sort keys for the flavor list (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt;) and
flavor list with details (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/detail&lt;/span&gt;&lt;/code&gt;) APIs. This field was only
supported by the long since removed XenAPI driver and is a no-op in modern
Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-FLV-DISABLED:disabled&lt;/span&gt;&lt;/code&gt; field from the flavor list
with details (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors/detail&lt;/span&gt;&lt;/code&gt;) and flavor show (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/flavors/{flavor_id}&lt;/span&gt;&lt;/code&gt;) APIs. There has never been a way to set this field,
making it a no-op.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, we will build on one of the above items and address some tech debt
with other schemas:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We will set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; for all query string
schemas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will restrict all action bodies to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;null&lt;/span&gt;&lt;/code&gt; values except those where a
value is actually expected.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We currently have to do this stuff client-side, which is less performant. We
could continue to do so.&lt;/p&gt;
&lt;p&gt;Rather than supporting a regex syntax, we could opt for a simple partial match
filter, implemented using the SQL &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LIKE&lt;/span&gt;&lt;/code&gt; operator. This is currently used for
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname_pattern&lt;/span&gt;&lt;/code&gt; filter of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-hypervisors&lt;/span&gt;&lt;/code&gt; API
(ultimately by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_node_search_by_hypervisor&lt;/span&gt;&lt;/code&gt; DB API). This would be
slightly more performant, but it would be less expressive and would result in a
potentially surprising difference in behavior compared to most other APIs.&lt;/p&gt;
&lt;p&gt;Regex support varies between our officially supported database backends,
MySQL/MariaDB and PostgreSQL, resulting in potential API behavioral differences
across deployments. We could investigate a subset of regex support that is
common across these backends and opt to support only this subset of patterns.
However, this is likely to be an involved, potentially complicated task that
would yield minimal benefit, given the &lt;a class="reference external" href="https://opendev.org/openstack/governance/commit/7999c374a391b6c702b9baafc6282649653e75a0"&gt;long-standing bias towards MySQL in
production deployments&lt;/a&gt; and absence of perceived issues with other APIs that
already suffer from this issue. Deferring to the backend’s regex support is
“good enough”.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavors&lt;/span&gt;&lt;/code&gt; model already has a &lt;a class="reference external" href="https://github.com/openstack/nova/blob/64ca204c9cf497b0dcfff2d3a24b0dd795a57d1d/nova/db/api/models.py#L231"&gt;unique
constraint&lt;/a&gt; and is therefore indexed. In addition, we do not plan to remove
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; field from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavor&lt;/span&gt;&lt;/code&gt; o.v.o. We may wish to remove the
field from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavors&lt;/span&gt;&lt;/code&gt; model but that should likely be done in a future
release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt; API will be modified to add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt;
query string filter parameter in requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/flavors&lt;/span&gt;&lt;/code&gt; API will be modified to remove support for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; parameter in requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All flavors API will be modified to remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rxtx_factor&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-FLV-DISABLED:disabled&lt;/span&gt;&lt;/code&gt; fields from responses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All API that currently accept an unrestricted set of query string parameters
will be modified to restrict these.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All action APIs that currently restrict an unrestricted value in request
bodies will be modified to only accept &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;null&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;openstackclient and third-party clients can take advantage of this when
filtering flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None. Clients will be faster since they can take advantage of server-side
filtering, but there should be no impact on the server itself since the field
is indexed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend API and rework schemas as described above&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We will provide new unit and functional tests, including API sample tests.&lt;/p&gt;
&lt;p&gt;We will extend the Compute API schemas used in Tempest to reflect these
changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update API ref.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 30 Jan 2025 00:00:00 </pubDate></item><item><title>Support for tracking traits removed from provider.yaml</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.2/approved/copy-applied-provider-yaml.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/copy-applied-provider-yaml"&gt;https://blueprints.launchpad.net/nova/+spec/copy-applied-provider-yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes a feature to ensure that traits removed from the
provider.yaml are also properly deleted from the resource provider.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova-compute has a feature to register custom traits with the resource provider
using config files (provider.yaml).
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html"&gt;https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this configuration file, even if the values of custom traits are modified or
the trait is deleted, the original trait does not be removed from the target
resource provider.
In scenarios where the custom trait registered with the resource provider is
replaced and old custom traits affect scheduling, this behavior can be a
problem.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud operator, I would like to ensure that only one trait is registered
with the resource provider for custom traits of the same type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud operator, I would like to complete the registration of custom
traits in the config file of nova-compute without additional implementation
(calling the Placement API using API/CLI in another system).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose adding a process for nova-compute to copy the contents of the
provider.yaml file to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/nova/applied_provider.yaml&lt;/span&gt;&lt;/code&gt; after they have
been applied to the placement.&lt;/p&gt;
&lt;p&gt;Then, when updating the placement based on the provider.yaml file, nova-compute
perform a diff between &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/nova/applied_provider.yaml&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/etc/nova/provider.yaml&lt;/span&gt;&lt;/code&gt; to detect if any traits have been removed from the
provider.yaml file.&lt;/p&gt;
&lt;p&gt;For now, the diff is limited to traits, but later this logic can be extended to
allow the use of the diff for any part of the provider.yaml.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Register only the custom traits defined in the file with the resource
provider, treating provider.yaml as declarative data. However, this is a
destructive change and there are concerns about the impact on the existing
environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a definition like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;declarative_prefix&lt;/span&gt;&lt;/code&gt; to provider.yaml to handle only
traits with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;declarative_prefix&lt;/span&gt;&lt;/code&gt; declaratively. In this case, the
extensibility to non-trait elements in provider.yaml is limited, and both the
definition in provider.yaml and the code of the resource tracker become
complex.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No performance impact on nova is anticipated. If there are frequent updates to
custom traits, requests for deleting and creating traits will be frequently
sent to the Placement API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mkuroha&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the copying of provider.yaml and extraction of trait diffs with
applied_provider.yaml in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_merge_provider_configs&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add unit/functional tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the existing &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html"&gt;Managing Resource Providers Using Config Files&lt;/a&gt; guide
to explation the behavior with applied_provider.yaml.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.2 Flamingo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 12 Dec 2024 00:00:00 </pubDate></item><item><title>vTPM live migration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/vtpm-live-migration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/vtpm-live-migration"&gt;https://blueprints.launchpad.net/nova/+spec/vtpm-live-migration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When Nova first added vTPM support, all non-spawn operations were &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/741500"&gt;rejected&lt;/a&gt; at the API level. Extra
work was necessary to manage the vTPM state when moving an instance. This work
was eventually completed for resize and cold migration, and those operations
were &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/639934/52"&gt;unblocked&lt;/a&gt;.
The blocks on live migration, evacuation, shelving and rescue are &lt;a class="reference external" href="https://docs.openstack.org/nova/2024.2/admin/emulated-tpm.html#limitations"&gt;still in
place&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A TPM device is &lt;a class="reference external" href="https://learn.microsoft.com/en-us/windows-server/get-started/hardware-requirements"&gt;required for certain features&lt;/a&gt;
of Windows Server 2022 and 2025, notably BitLocker Drive Encryption. It’s also
required to run &lt;a class="reference external" href="https://www.microsoft.com/en-us/windows/windows-11-specifications"&gt;Windows 11 at all&lt;/a&gt;. The
inability to live migrate instances with vTPM is a major roadblock for anyone
operating Windows guests in an OpenStack cloud.&lt;/p&gt;
&lt;p&gt;Libvirt support for vTPM live migration now exists (more details in
&lt;a class="reference internal" href="#problem-description"&gt;&lt;span class="std std-ref"&gt;Problem description&lt;/span&gt;&lt;/a&gt;), but Nova changes are necessary before being able
to remove the API block. This spec describes those changes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;span id="id1"/&gt;&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are four aspects to vTPM live migration: shared vs non-shared vTPM state
storage, Libvirt support, and secret management. There is also an adjacent
problem, that - while not related to live migration - can be resolved by the
changes necessary to support live migration: vTPM instances cannot be started
back up by Nova after a compute host reboot.&lt;/p&gt;
&lt;section id="vtpm-state-storage"&gt;
&lt;h3&gt;vTPM state storage&lt;/h3&gt;
&lt;p&gt;vTPM state storage is not the same as instance state storage. The latter can be
configued to be shared, for example on NFS. The former is always non-shared.
Libvirt can be told where to store the vTPM state via the &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#tpm-device"&gt;source&lt;/a&gt; XML element, which Nova
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/config.py#L1146-L1153"&gt;does not support&lt;/a&gt;.
Nova deployments use the Libvirt default vTPM state path. On both Ubuntu and
Red Hat operating systems, this path is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/libvirt/swtpm/&amp;lt;instance&lt;/span&gt;
&lt;span class="pre"&gt;UUID&amp;gt;&lt;/span&gt;&lt;/code&gt;. This path is distinct from the instance state path and can be expected
to never be on shared storage.&lt;/p&gt;
&lt;p&gt;Thus, this spec requires vTPM state storage to be not shared, and declares live
migration with shared vTPM state storage to be untested. This will be
documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="libvirt-support"&gt;
&lt;h3&gt;Libvirt support&lt;/h3&gt;
&lt;p&gt;Though it was impossible to find Libvirt artifacts explicitly demonstrating
vTPM live migration support for non-shared vTPM state storage, as of &lt;a class="reference external" href="https://www.libvirt.org/news.html#v8-10-0-2022-12-01"&gt;version
8.10&lt;/a&gt;, vTPM live
migration with shared vTPM storage is supported, and &lt;a class="reference external" href="https://github.com/stefanberger/swtpm/issues/525#issuecomment-914542936"&gt;this comment&lt;/a&gt;
suggests that for non-shared storage, vTPM live migration has been supported
since version 7.1.0.&lt;/p&gt;
&lt;p&gt;Therefore, this spec requires Libvirt 7.1.0.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="secret-management"&gt;
&lt;h3&gt;Secret management&lt;/h3&gt;
&lt;p&gt;When creating an instance with vTPM, Nova asks a key manager - normally
Barbican - to generate a secret. Crucially, this is done with the user’s token,
and the created secret is owned by the user, with no one else - not even admin
or the Nova service user - being able to read it. Nova then &lt;a class="reference external" href="https://libvirt.org/formatsecret.html"&gt;defines the secret
in Libvirt&lt;/a&gt;, and in the instance XML
references the secret by its UUID. This tells Libvirt to encrypt the instance’s
vTPM state using the contents of that secret as the symmetric key. Nova
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/driver.py#L8077"&gt;undefines the secret&lt;/a&gt;
once the Libvirt domain spawns successfully.&lt;/p&gt;
&lt;p&gt;For vTPM live migration to work, a Libvirt secret with the same UUID and
contents needs to be defined on the destination host so that destination
Libvirt can decrypt the vTPM state. Currently, Nova has no way of doing this.
Live migration is an admin operation, and neither admin nor the Nova service
user have access to the Barbican secret (unless the admin happens to be the
owen of the instance, but that’s an edge case). The Libvirt secret cannot be
read back on the source host either, because it’s defined as &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/c79bec0f2257967da1dcccc9f562253d6ede535d/nova/virt/libvirt/host.py#L1115-L1116"&gt;private&lt;/a&gt;
and is undefined once the domain spawns.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="compute-host-reboot"&gt;
&lt;h3&gt;Compute host reboot&lt;/h3&gt;
&lt;p&gt;For the exact same reasons (lack of Barbican secret access and inability to
read the Libvirt secret back from Libvirt), Nova cannot start back up vTPM
instances after a compute host reboot.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a cloud operator, I want to be able to live migrate instances with vTPM
devices, in particular Windows instances.&lt;/p&gt;
&lt;p&gt;As a cloud user, I want to keep the contents of my instance’s vTPM private.
The cloud system should only be able to decrypt it when I request it via my
user token and the system should only keep the decryption secret around for a
limited time. I as a user am willing to accept that such privacy requirements
limit some of the admin initiated lifecycle operations on my instance.&lt;/p&gt;
&lt;p&gt;As a cloud operator, I want vTPM instances on a compute host to start back up
again after a host reboot.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Because the security of the vTPM secret (either in Barbican or in Libvirt)
affects what operations can be performed on an instance, users should be able
to specify what level of security they require, and operators need to specify
what level of security they’re willing to support. There also needs to be a
default level applied to an instance if nothing is explicitly specified.&lt;/p&gt;
&lt;p&gt;Three possible security levels are proposed. They are presented in the table
below.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_secret_security&lt;/span&gt;&lt;/code&gt; values&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Mechanism&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Security implications&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Instance mobility&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Only the instance owner has access to the Barbican secret. This is existing
behavior.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is the most secure option, as even the Nova service user and root on
the compute host cannot read the secret.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance is immovable and cannot be restarted by Nova in the event of a
compute host crash or reboot.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The Libvirt secret is persistent and retrievable.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is “medium” security. API-level admins and the Nova service user do
not have access to the secret, but it can be accessed by users with
sufficient privileges on the compute host.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance can be live migrated because Nova can read the secret back
from Libvirt on the source host and send it to the destination over RPC.
Security over the wire is left as the operator’s responsibility, but TLS or
similar is assumed. The instance can also be restarted by Nova in the event
of a compute host crash or reboot for the exact same reason.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The Nova service user owns the Barbican secret.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;This is the least secure but most flexible option.&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The instance can be live migrated because Nova can download the secret from
Barbican and define it in Libvirt on the destination host. The instance can
also be restarted by Nova in the event of a compute host crash or reboot
for the exact same reason.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Users are able to chose what level they require on their instance by setting
the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; image property. If this property is not
set, a default can be obtained from the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:vtpm_secret_security&lt;/span&gt;&lt;/code&gt; flavor
extra spec. For operators that do not want to deal with flavor explosion as a
consequence of this new extra spec, a new host configuration option is added as
a fallback. Called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]vtpm_secret_security&lt;/span&gt;&lt;/code&gt; with a default value of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;, an instance with no image property or flavor extra spec will have its
host’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_secret_security&lt;/span&gt;&lt;/code&gt; policy persisted in its &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;
upon booting on that host.&lt;/p&gt;
&lt;p&gt;Operators ae able to specify what level they support by using the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]supported_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; config option. This is a
per compute host list option that can take the value of one or more of the
security levels from the previous table. Its default value is all three levels.
These values are exposed as driver capability traits. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_Security&lt;/span&gt;&lt;/code&gt; image property and flavor extra spec are translated
to required traits to match the driver capabilities.&lt;/p&gt;
&lt;p&gt;The behavior of an instance during live migratioon is defined by its persisted
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; (either explicitly set by the user, or added by
default by Nova from the host’s config option). Instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user&lt;/span&gt;&lt;/code&gt; cannot
be live migrated. For instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;, the source compute host reads
the secret from Libvirt and sends it over RPC to the destination. For instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt;, the destination host downloads the secret from Barbican
and defines it in Libvirt. Because the instance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt;
value translates to a required trait, it’s guaranteed that the destination host
chosen for live migration supports whatever behavior the instance requires.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This is the only version of this spec that covers the essentials: users with
existing instances are informed of the vTPM secret security level set on their
instances by the operator, users of new instances can chose the security level
that they require, and operators can chose which security levels they are
willing to support given the limitations imposed by higher security levels.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetaProps&lt;/span&gt;&lt;/code&gt; Nova object is updated to support the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; image property. The database schema is unaffected.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;No new microversion. The flavor extra spec validation code is updated to allow
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:vtpm_secret_security&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The main security consequences of this spec are the implications of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; values of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_secret_security&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; case, anyone with sufficient access to the compute host can
read vTPM secrets. While this is not great, it’s also something the user opts
in to, and the compute host are assumed to be secured by the cloud operator.&lt;/p&gt;
&lt;p&gt;In the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; case, a compromise of the Nova service user leads to an
exposure of all vTPM secrets. Once again, this is something the user opts in
to, and the Nova service user is assumed to be secure.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A compute service version bump is necessary. When nova-compute starts up with
the new service version, it checks all instances currently on the host. Any
instances created after the service version bump have a value for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; set in their &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;, either explicitly
by the user or implicitly by Nova as  a fallback default, as described in the
&lt;cite&gt;&amp;lt;Proposed change_&amp;gt;_&lt;/cite&gt; section. Any instances without this set are pre-existing
instances, and need to be upgraded. They are upgraded to the value of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]default_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; value. Just persisting this in their
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; is not enough - their owner also needs to performa an
operation with their token on the instance so that Nova can either convert the
Libvirt secret to non-private and persistent in the case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;, or create
a new Barbican secret with the same contents, but owned by the Nova service
user, in the case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt;. Operators have no choice but to
communicate this to their users, at which point users have a choice to either
opt in to the new security level, or refuse by not touching their instances or
deleting them outright. In order to see what secret security level has been set
on their instances by the operators, this spec depends on the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/938910"&gt;Image props in
server show&lt;/a&gt;
spec, which will allow users to see the embedded image properties set on their
instance, and determine the vTPM secret security level that way.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;notartom&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt, dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vtpm_secret_security&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:vtpm_secret_security&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]vtpm_secret_security&lt;/span&gt;&lt;/code&gt;, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]default_vtpm_secret_security&lt;/span&gt;&lt;/code&gt; image properties, flavor extra
specs, and config options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the pre live migration and rollback code to handle secret definition
and cleanup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bump the service version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the existing API block to only allow live migration of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deployment&lt;/span&gt;&lt;/code&gt; instances once the minimum service version has reached the
bumped version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a whitebox/integration test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Libivrt version 7.1.0. This can be enforced dynamically in code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Nova’s functional tests are extended to test the Nova logic using the Libvirt
fixture. This is particularly useful for cases that cannot be easily tested in
a real environment, like rollback.&lt;/p&gt;
&lt;p&gt;The existing &lt;a class="reference external" href="https://opendev.org/openstack/whitebox-tempest-plugin/src/commit/bee34dbb867dc3c107f1262f68a997ef7ccff55a/whitebox_tempest_plugin/api/compute/test_vtpm.py"&gt;whitebox-tempest-plugin vTPM tests&lt;/a&gt;
are extended to test live migration in a real environment with an actual
Libvirt.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Nova’s &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/emulated-tpm.html"&gt;vTPM documentation&lt;/a&gt; is updated
to remove the live migration limitation and explain the usage of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_secret_security&lt;/span&gt;&lt;/code&gt; configuration option, as well as the implications of
all possible values. The expectation that vTPM state storage is not shared and
that shared vTPM state storage live migration is untested is made explicit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Empty.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 21 Nov 2024 00:00:00 </pubDate></item><item><title>Support Cinder Volume Multi-attach</title><link>https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/multi-attach-volume.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/multi-attach-volume"&gt;https://blueprints.launchpad.net/nova/+spec/multi-attach-volume&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, Nova only allows a volume to be attached to a single
instance.  There are times when a user may want to be able
to attach the same volume to multiple instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Nova is not prepared to attach a single Cinder volume to
multiple VM instances even if the volume itself allows that operation.
This document describes the required changes in Nova to introduce this new
functionality and also lists the limitations it has.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Allow users to share volumes between multiple guests using read-write
attachments like clustered applications with two nodes where one is active and
one is passive. Both require access to the same volume although only one
accesses actively. When the active one goes down, the passive one can take
over quickly and has access to the data.&lt;/p&gt;
&lt;p&gt;The above example works with active/active scenario as well, it’s the user’s
responsibility to choose the right filesystem.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The new ‘multi-attach’ functionality will be enabled by using the new Cinder
attach/detach API which is available from the API microversion 3.44 &lt;a class="footnote-reference brackets" href="#id6" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cinder will only allow a volume to be attached more than once if its
‘multiattach’ flag is set on the volume at create time. Nova is expected to
rely on Cinder to do the check on the volume state when it’s reserving the
volume on the API level by calling attachment_create.&lt;/p&gt;
&lt;p&gt;There are problems today when multiple volume attachments share a single
target to the volume backend &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. If we do not take care, multi-attach would
make these problems much worse. The simplest fix is to serialize all attach and
detach operations involving a shared target. To do this Cinder will expose
a volume info property of ‘shared_targets’, when True a lock will be
placed around all attachment_update and attachment_delete calls, and the
associated calls to os-brick.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# The lock uses the volume.backend_uuid value.&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;optional_host_local_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acquire&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared_target&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;connector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os_brick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_connector&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;conn_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conn_info&lt;/span&gt;
  &lt;span class="n"&gt;os_brick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect_volume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attach_complete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;optional_host_local_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acquire&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared_target&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;os_brick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disconnect_volume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We assume the detach and attach related calls to Cinder are synchronous so
there will be no races between os-brick operations on the host and cinder
operations on the backend. Any driver deviation from this pattern will be
considered a bug.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;By default libvirt assumes all disks are exclusively used by a single guest.
If you want to share disks between instances, you need to tell libvirt
when configuring the guest XML for that disk via setting the ‘shareable’ flag
for the disk. This means that the hypervisor will not try to take an exclusive
lock on the disk, that all I/O caching is disabled, and any SELinux labeling
allows use by all domains.&lt;/p&gt;
&lt;p&gt;Nova needs to set this ‘shareable’ flag for the multi-attach volumes (where the
‘multattach’ flag is set to True) for every single attachment. This spec will
only enable this feature for libvirt, all other drivers should reject attach
calls to multi-attach volumes, until that driver adds support to this
functionality. The information is stored among the virt driver capabilities
dict in the base ComputeDriver where support multi-attach will be True for
Libvirt and for all other virt drivers this capability is disabled. To
introduce the usage of the flag we will also need to bump the minimum compute
version.&lt;/p&gt;
&lt;p&gt;The following policy rules will be added to Cinder:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enable/Disable multiattach=True&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable/Disable multiattach=True + bootable=True&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nova should reject the attach request in case the hypervisor does not support
it, but with the current API it is not possible. This can be solved in part
with the policy rules above. For example, if you’re running a cloud with
computes that don’t support multiattach, let’s say it’s all vmware, then the
operator can configure policy to disable multiattach volumes on the cinder
side. If you’ve got a mixed hypervisor cloud and the user tries to attach a
multiattach volume to an instance on a compute where the virt driver doesn’t
support multiattach, then the attach request fails on the compute and
nova-compute calls attachment_delete to delete the attachment created in
nova-api’s attach_volume code. If nova-api exposed backend compute driver
capabilities then we could check and fail fast in the API, but nova doesn’t
have that yet so we’re just left with policy rules and checks on the backend.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;For the use case described above the failover scenario can be handled by
attaching the volume to the passive/standby instance. This means that the
standby instance is not a hot standby anymore as the volume attachment
requires time, which means that the new primary instance is without volume
for the time of re-attaching, which can vary in the sense of marking the
volume free after the failure of the primary instance.&lt;/p&gt;
&lt;p&gt;Another alternative is to clone a volume and attach the clone to the second
instance. The downside to this is any changes to the original volume don’t
show up in the mounted clone so this is only a viable alternative if the
volume is read-only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There are features of the Nova API that has to be handled by care or disabled
completely for now for volumes that support multi-attach.&lt;/p&gt;
&lt;p&gt;The create call in the ‘os-assisted-volume-snapshot’ API calls the
‘volume_snapshot_create’ where we don’t have the instance_uuid to retrieve the
right BDM, therefore we need to disable this call for multi-attach. The API
format for this request is not changed, it is only a protection until the
required API changes to support this request with multi-attach.&lt;/p&gt;
&lt;p&gt;Another feature that needs further investigation is ‘boot from volume’ (BFV).
The first aspect of the feature is the ‘delete_on_termination’ flag, which will
be allowed to use along with multi-attach, no changes are necessary when the
volume provided has multiattach=True and the delete_on_termination=True flag is
passed in for BFV. When this flag is set to True it is intended to remove the
volume that is attached to the instance when it is deleted. This option does
not cause problem as Cinder takes care of not deleting a volume if it still
has active attachments. Nova will receive an error from Cinder that the volume
deletion failed, which will then be logged &lt;a class="footnote-reference brackets" href="#id8" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and also in the API on
‘_local_delete’ &lt;a class="footnote-reference brackets" href="#id9" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but will not affect the instance termination process.&lt;/p&gt;
&lt;p&gt;The second aspect of BFV is the boot process. In this case Nova only checks the
‘bootable’ flag. The policy check happens on the Cinder side on allowing it
together with multiattach or not.&lt;/p&gt;
&lt;p&gt;For cases, where Nova creates the volume itself, i.e. source_type is
blank/image/snapshot, it should not enable multi-attach for the volume, i.e. no
change to the existing code for now.&lt;/p&gt;
&lt;p&gt;When we attach a volume at boot time (BFV with source=volume,dest=volume)
scheduling will fail in case of selecting computes that do not support
multi-attach. Later on we can add a new scheduler filter to avoid the failure.
The filter would check the compute capabilities. This step is considered
to be a future improvement.&lt;/p&gt;
&lt;p&gt;When we enable the feature we will have a ‘multiattach’ policy to enable or
disable the operation entirely on the Cinder side as noted above. Read/Only
policy is a future work item and out of the scope of this spec.&lt;/p&gt;
&lt;p&gt;A new compute API microversion will be added since users will need
some way to discover if they can perform volume multiattach. The semantics
of the microversion will be similar to the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id44"&gt;2.49&lt;/a&gt; microversion for tagged
attach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;In the libvirt driver, the disk is given a shared SELinux label,
and so that disk has no longer strong sVirt SELinux isolation.&lt;/p&gt;
&lt;p&gt;The OpenStack volume encryption capability is supposed to work out of the
box with this use case also, it should not break how the encryptor works
below the clustered file system, by using the same key for all connections.
The attachment of an encrypted volume to multiple instances should be
tested in Tempest to see if there is any unexpected issue with it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;Based on the work from Walter Boring and Charlie Zhou.
Agreed with Walter to start the work again.&lt;/p&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ildiko-vancsa&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Update libvirt driver to generate proper domain XML for instances with
multi-attach volumes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide the necessary checks in the Nova API to block the operation in the
above listed cases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add Tempest test cases and documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This requires the version 3.2.0 or above of the python-cinderclient.
Corresponding blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/python-cinderclient/+spec/multi-attach-volume"&gt;https://blueprints.launchpad.net/python-cinderclient/+spec/multi-attach-volume&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Corresponding, implemented spec in Cinder:
&lt;a class="reference external" href="https://blueprints.launchpad.net/cinder/+spec/multi-attach-volume"&gt;https://blueprints.launchpad.net/cinder/+spec/multi-attach-volume&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Link needed to Cinder spec to address detach issues currently captured here:
&lt;a class="reference external" href="https://etherpad.openstack.org/p/cinder-nova-api-changes"&gt;https://etherpad.openstack.org/p/cinder-nova-api-changes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We’ll have to add new Tempest tests to support the new Cinder volume
multiattach flag. The new cinder multiattach flag is what allows a volume to be
attached more than once. For instance the following scenarios will need to be
tested:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Attach the same volume to two instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Boot from volume with multiattach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encrypted volume with multiattach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Boot from multi-attachable volume with boot_index=0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Negative testing:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Tying to attach a non-multiattach volume to multiple instances&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Additionally to the above, Cinder migrate needs to be tested on the gate, as it
triggres swap_volume in Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We will have to update the documentations to discuss the new ability to
attach a volume to multiple instances if the cinder multiattach flag is set
on a volume. It is also need to be added to the documentation that the volume
creation for these types of volumes will not be supported by the API due to
the deprecation of the volume creation Nova API. If a volume needs to allow
multiple volume attachments it has to be created on the Cinder side with
the needed properties specified.&lt;/p&gt;
&lt;p&gt;It also needs to be outlined in the documentation that attaching a volume
multiple times in read-write mode can cause data corruption, if not handled
correctly. It is the users’ responsibility to add some type of exclusion
(at the file system or network file system layer) to prevent multiple writers
from corrupting the data. Examples should be provided if available to guide
users on how to do this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This is the cinder wiki page that discusses the approach to multi-attach
&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Cinder/blueprints/multi-attach-volume"&gt;https://wiki.openstack.org/wiki/Cinder/blueprints/multi-attach-volume&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queens PTG etherpad:
&lt;a class="reference external" href="https://etherpad.openstack.org/p/cinder-ptg-queens-thursday-notes"&gt;https://etherpad.openstack.org/p/cinder-ptg-queens-thursday-notes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id41"&gt;https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id41&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2016-May/094089.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2016-May/094089.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/295224c41e7da07c5ddbdafc72ac5abf2d708c69/nova/compute/manager.py#L2369"&gt;https://github.com/openstack/nova/blob/295224c41e7da07c5ddbdafc72ac5abf2d708c69/nova/compute/manager.py#L2369&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/295224c41e7da07c5ddbdafc72ac5abf2d708c69/nova/compute/api.py#L1834"&gt;https://github.com/openstack/nova/blob/295224c41e7da07c5ddbdafc72ac5abf2d708c69/nova/compute/api.py#L1834&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id10"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Kilo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Liberty&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Mitaka-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Mitaka-2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated with API limitations and testing scenarios&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Newton&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Queens&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 08 Nov 2024 00:00:00 </pubDate></item><item><title>Use OpenStack SDK in Nova</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/approved/openstacksdk-in-nova.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/openstacksdk-in-nova"&gt;https://blueprints.launchpad.net/nova/+spec/openstacksdk-in-nova&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to use the OpenStack SDK to interact with other core OpenStack
services.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova is using both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and keystoneauth1 adapters to
interact with other core services. Currently changes or fixes to a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt;
that Nova depends on may require changes to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; before
Nova can be brought into parity. This also requires the OpenStack SDK to be
brought into parity as it is used for the CLI.&lt;/p&gt;
&lt;p&gt;Maintenance of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; can be burdensome due to high
technical debt in the clients. By consuming the OpenStack SDK directly, we can
eliminate the additional dependency on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and
streamline the process.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a developer on OpenStack, I would like to reduce the number of areas where
maintenance must be performed when making changes related to the use of core
OpenStack services.&lt;/p&gt;
&lt;p&gt;As a core OpenStack project, Nova should make use of other projects in reliable
and maintainable ways. To this end, we should use the OpenStack SDK for service
to service interaction in place of direct API or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt;
implementations.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to use the OpenStack SDK in place of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and other methods across Nova in three phases for
each of the target services.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Services:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ironic (python-ironicclient -&amp;gt; Baremetal SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cinder (python-cinderclient -&amp;gt; Block Storage SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance (python-glanceclient -&amp;gt; Image v2 SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron (python-neutronclient -&amp;gt; Network SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Placement (keystoneauth1 adapter -&amp;gt; OpenStack SDK Proxy)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The &lt;strong&gt;initial phase&lt;/strong&gt; will consist of adding plumbing to construct an
openstack.connection.Connection object to Nova components that interact with
other services using a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt;. The service proxy from this
connection can then be used in place of existing keystoneauth1 adapter to
retrieve the endpoint to configure the client. This is in progress at
[&lt;a class="footnote-reference brackets" href="#sdk-in-nova" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;main phase&lt;/strong&gt; will be to iterate through calls to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and replace them with calls into the OpenStack SDK
until the client is no longer needed. During this phase, we will close
feature deficiencies identified in the OpenStack SDK as necessary. See
&lt;a class="reference internal" href="#openstack-sdk-changes"&gt;OpenStack SDK Changes&lt;/a&gt; for a list of identified deficiencies. This process is
in progress for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-ironicclient&lt;/span&gt;&lt;/code&gt; at [&lt;a class="footnote-reference brackets" href="#sdk-for-ironic" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;For Placement, replace the keystoneauth1 adapter returned by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.utils.get_ksa_adapter('placement')&lt;/span&gt;&lt;/code&gt; with the SDK’s placement proxy.
This is transparent other than a small number of changes to mocks in tests.
This is in progress at [&lt;a class="footnote-reference brackets" href="#sdk-for-placement" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;]. Eventually, the SDK may
implement more support for placement. With the framework being in place, we can
consider integrating such changes as they become available.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;final phase&lt;/strong&gt; will simply be to remove the now-unused clients and clean
up any remaining helpers and fixtures.&lt;/p&gt;
&lt;section id="openstack-sdk-changes"&gt;
&lt;h3&gt;OpenStack SDK Changes&lt;/h3&gt;
&lt;p&gt;The OpenStack SDK includes a more complete selection of helpers for some
services than others, but at worst provides the same primitives as a
keystoneauth1 adapter. Development has started with Ironic, which has robust
support within the OpenStack SDK. Other services will require additional work
in the OpenStack SDK, or may need to be implemented using the API primitives
provided by openstack.Proxy. It is more desirable to focus on expanding
OpenStack SDK support for these projects rather than implementing them in Nova.
Since there is not a spec repo for OpenStack SDK, we will try to outline the
missing helpers by service here.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;strong&gt;Ironic&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;node.get_console&lt;/div&gt;
&lt;div class="line"&gt;node.inject_nmi&lt;/div&gt;
&lt;div class="line"&gt;node.list_volume_connectors&lt;/div&gt;
&lt;div class="line"&gt;node.list_volume_targets&lt;/div&gt;
&lt;div class="line"&gt;node.set_console_mode (available via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;patch_node&lt;/span&gt;&lt;/code&gt;)&lt;/div&gt;
&lt;div class="line"&gt;volume_target.create&lt;/div&gt;
&lt;div class="line"&gt;volume_target.delete&lt;/div&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;strong&gt;Cinder&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;attachments.complete&lt;/div&gt;
&lt;div class="line"&gt;attachments.delete&lt;/div&gt;
&lt;div class="line"&gt;attachments.update&lt;/div&gt;
&lt;div class="line"&gt;volumes.attach&lt;/div&gt;
&lt;div class="line"&gt;volumes.begin_detaching&lt;/div&gt;
&lt;div class="line"&gt;volumes.detach&lt;/div&gt;
&lt;div class="line"&gt;volumes.initialize_connection&lt;/div&gt;
&lt;div class="line"&gt;volumes.migrate_volume_completion&lt;/div&gt;
&lt;div class="line"&gt;volumes.reserve&lt;/div&gt;
&lt;div class="line"&gt;volumes.roll_detaching&lt;/div&gt;
&lt;div class="line"&gt;volumes.terminate_connection&lt;/div&gt;
&lt;div class="line"&gt;volumes.unreserve&lt;/div&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;strong&gt;Glance&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;image.add_location&lt;/div&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;strong&gt;Neutron&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;None&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One possibility that was considered was to replace calls into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; with methods that invoke the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt; APIs
directly through the keystoneauth1 adapter’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get/put/etc&lt;/span&gt;&lt;/code&gt; primitives. This
would entail effectively porting the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; code into
nova. While this would give us the opportunity to clean things up, it would
involve a lot of low-level work like version discovery/negotiation, input
payload construction and validation, and output processing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The initial phase will have minimal impact as the only change is the
construction of the keystoneauth1 adapter by the OpenStack SDK rather than
directly. The main phase will not likely have any difference in performance and
the final phase should approximately offset any impact from the initial phase.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;By using the OpenStack SDK as the single method of contact with other services,
the maintenance footprint can be reduced. This also moves us towards a more
stable OpenStack SDK as more consumers generally mean more chances to find and
resolve bugs.&lt;/p&gt;
&lt;p&gt;In addition, as new methods and services are supported by the OpenStack SDK,
introducing them to Nova should be simpler and more reliable than the current
methods.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dustinc &amp;lt;&lt;a class="reference external" href="mailto:dustin.cowles%40intel.com"&gt;dustin&lt;span&gt;.&lt;/span&gt;cowles&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;, efried &amp;lt;&lt;a class="reference external" href="mailto:openstack%40fried.cc"&gt;openstack&lt;span&gt;@&lt;/span&gt;fried&lt;span&gt;.&lt;/span&gt;cc&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mordred &amp;lt;&lt;a class="reference external" href="mailto:mordred%40inaugust.com"&gt;mordred&lt;span&gt;@&lt;/span&gt;inaugust&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;, dtantsur &amp;lt;&lt;a class="reference external" href="mailto:dtantsur%40protonmail.com"&gt;dtantsur&lt;span&gt;@&lt;/span&gt;protonmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce package requirements to Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce plumbing for the construction of an
openstack.connection.Connection object for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each target &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt; (excluding Placement), close
deficiencies in OpenStack SDK while replace invocations into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; one at a time, with calls into the SDK’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt; proxy.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For Placement, replace the keystoneauth1 adapter with the
SDK’s placement proxy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the now-unused &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt;, test fixtures, and other
helpers and utils.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova support for using keystoneauth1 config options for Cinder.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/655985/"&gt;https://review.opendev.org/#/c/655985/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Existing unit tests will need to be updated to assert calls to the SDK instead
of the client. In cases where the client call was mocked, this should be a
matter of swapping out that mock and its assertions. No significant additional
unit testing should be required.&lt;/p&gt;
&lt;p&gt;Existing functional test cases should be adequate. Changes may be required in
fixtures and other framework.&lt;/p&gt;
&lt;p&gt;Existing integration tests should continue to function seamlessly. This will be
the litmus test of success.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="sdk-in-nova" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/643664/"&gt;https://review.opendev.org/#/c/643664/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="sdk-for-ironic" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/642899/"&gt;https://review.opendev.org/#/c/642899/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="sdk-for-placement" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/656023/"&gt;https://review.opendev.org/#/c/656023/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005810.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005810.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/openstacksdk/latest/user/config/configuration.html"&gt;https://docs.openstack.org/openstacksdk/latest/user/config/configuration.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-sdks/%23openstack-sdks.2019-05-20.log.html#t2019-05-20T13:48:07"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-sdks/%23openstack-sdks.2019-05-20.log.html#t2019-05-20T13:48:07&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 08 Nov 2024 00:00:00 </pubDate></item><item><title>Use OpenStack SDK in Nova</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/openstacksdk-in-nova.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/openstacksdk-in-nova"&gt;https://blueprints.launchpad.net/nova/+spec/openstacksdk-in-nova&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to use the OpenStack SDK to interact with other core OpenStack
services. Implementation began in Train and continues in Ussuri.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova is using both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and keystoneauth1 adapters to
interact with other core services. Currently changes or fixes to a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt;
that Nova depends on may require changes to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; before
Nova can be brought into parity. This also requires the OpenStack SDK to be
brought into parity as it is used for the CLI.&lt;/p&gt;
&lt;p&gt;Maintenance of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; can be burdensome due to high
technical debt in the clients. By consuming the OpenStack SDK directly, we can
eliminate the additional dependency on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and
streamline the process.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a developer on OpenStack, I would like to reduce the number of areas where
maintenance must be performed when making changes related to the use of core
OpenStack services.&lt;/p&gt;
&lt;p&gt;As a core OpenStack project, Nova should make use of other projects in reliable
and maintainable ways. To this end, we should use the OpenStack SDK for service
to service interaction in place of direct API or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt;
implementations.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to use the OpenStack SDK in place of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and other methods across Nova in three phases for
each of the target services.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Services:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ironic (python-ironicclient -&amp;gt; Baremetal SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cinder (python-cinderclient -&amp;gt; Block Storage SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance (python-glanceclient -&amp;gt; Image v2 SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron (python-neutronclient -&amp;gt; Network SDK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Placement (keystoneauth1 adapter -&amp;gt; OpenStack SDK Proxy)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The &lt;strong&gt;initial phase&lt;/strong&gt; will consist of adding plumbing to construct an
openstack.connection.Connection object to Nova components that interact with
other services using a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt;. The service proxy from this
connection can then be used in place of existing keystoneauth1 adapter to
retrieve the endpoint to configure the client. This is in progress at
[&lt;a class="footnote-reference brackets" href="#sdk-in-nova" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;main phase&lt;/strong&gt; will be to iterate through calls to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; and replace them with calls into the OpenStack SDK
until the client is no longer needed. During this phase, we will close
feature deficiencies identified in the OpenStack SDK as necessary. See
&lt;a class="reference internal" href="#openstack-sdk-changes"&gt;OpenStack SDK Changes&lt;/a&gt; for a list of identified deficiencies. This process is
in progress for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-ironicclient&lt;/span&gt;&lt;/code&gt; at [&lt;a class="footnote-reference brackets" href="#sdk-for-ironic" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;For Placement, replace the keystoneauth1 adapter returned by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.utils.get_ksa_adapter('placement')&lt;/span&gt;&lt;/code&gt; with the SDK’s placement proxy.
This is transparent other than a small number of changes to mocks in tests.
This is in progress at [&lt;a class="footnote-reference brackets" href="#sdk-for-placement" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;]. Eventually, the SDK may
implement more support for placement. With the framework being in place, we can
consider integrating such changes as they become available.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;final phase&lt;/strong&gt; will simply be to remove the now-unused clients and clean
up any remaining helpers and fixtures.&lt;/p&gt;
&lt;section id="openstack-sdk-changes"&gt;
&lt;h3&gt;OpenStack SDK Changes&lt;/h3&gt;
&lt;p&gt;The OpenStack SDK includes a more complete selection of helpers for some
services than others, but at worst provides the same primitives as a
keystoneauth1 adapter. Development has started with Ironic, which has robust
support within the OpenStack SDK. Other services will require additional work
in the OpenStack SDK, or may need to be implemented using the API primitives
provided by openstack.Proxy. It is more desirable to focus on expanding
OpenStack SDK support for these projects rather than implementing them in Nova.
Since there is not a spec repo for OpenStack SDK, we will try to outline the
missing helpers by service here.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;strong&gt;Ironic&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;node.get_console&lt;/div&gt;
&lt;div class="line"&gt;node.inject_nmi&lt;/div&gt;
&lt;div class="line"&gt;node.list_volume_connectors&lt;/div&gt;
&lt;div class="line"&gt;node.list_volume_targets&lt;/div&gt;
&lt;div class="line"&gt;node.set_console_mode (available via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;patch_node&lt;/span&gt;&lt;/code&gt;)&lt;/div&gt;
&lt;div class="line"&gt;volume_target.create&lt;/div&gt;
&lt;div class="line"&gt;volume_target.delete&lt;/div&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;strong&gt;Cinder&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;attachments.complete&lt;/div&gt;
&lt;div class="line"&gt;attachments.delete&lt;/div&gt;
&lt;div class="line"&gt;attachments.update&lt;/div&gt;
&lt;div class="line"&gt;volumes.attach&lt;/div&gt;
&lt;div class="line"&gt;volumes.begin_detaching&lt;/div&gt;
&lt;div class="line"&gt;volumes.detach&lt;/div&gt;
&lt;div class="line"&gt;volumes.initialize_connection&lt;/div&gt;
&lt;div class="line"&gt;volumes.migrate_volume_completion&lt;/div&gt;
&lt;div class="line"&gt;volumes.reserve&lt;/div&gt;
&lt;div class="line"&gt;volumes.roll_detaching&lt;/div&gt;
&lt;div class="line"&gt;volumes.terminate_connection&lt;/div&gt;
&lt;div class="line"&gt;volumes.unreserve&lt;/div&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;strong&gt;Glance&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;image.add_location&lt;/div&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;strong&gt;Neutron&lt;/strong&gt;&lt;/div&gt;
&lt;div class="line"&gt;None&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One possibility that was considered was to replace calls into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; with methods that invoke the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt; APIs
directly through the keystoneauth1 adapter’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get/put/etc&lt;/span&gt;&lt;/code&gt; primitives. This
would entail effectively porting the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; code into
nova. While this would give us the opportunity to clean things up, it would
involve a lot of low-level work like version discovery/negotiation, input
payload construction and validation, and output processing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The initial phase will have minimal impact as the only change is the
construction of the keystoneauth1 adapter by the OpenStack SDK rather than
directly. The main phase will not likely have any difference in performance and
the final phase should approximately offset any impact from the initial phase.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;By using the OpenStack SDK as the single method of contact with other services,
the maintenance footprint can be reduced. This also moves us towards a more
stable OpenStack SDK as more consumers generally mean more chances to find and
resolve bugs.&lt;/p&gt;
&lt;p&gt;In addition, as new methods and services are supported by the OpenStack SDK,
introducing them to Nova should be simpler and more reliable than the current
methods.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dustinc &amp;lt;&lt;a class="reference external" href="mailto:dustin.cowles%40intel.com"&gt;dustin&lt;span&gt;.&lt;/span&gt;cowles&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mordred &amp;lt;&lt;a class="reference external" href="mailto:mordred%40inaugust.com"&gt;mordred&lt;span&gt;@&lt;/span&gt;inaugust&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;, dtantsur &amp;lt;&lt;a class="reference external" href="mailto:dtantsur%40protonmail.com"&gt;dtantsur&lt;span&gt;@&lt;/span&gt;protonmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;efried&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;(Implemented in Train) Introduce package requirements to Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Partially implemented in Train) Introduce plumbing for the construction of
an openstack.connection.Connection object for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Partially Implemented in Train) For each target &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt; (excluding
Placement), close deficiencies in OpenStack SDK while replace invocations
into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt; one at a time, with calls into the SDK’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$service&lt;/span&gt;&lt;/code&gt; proxy.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For Placement, replace the keystoneauth1 adapter with the
SDK’s placement proxy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the now-unused &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-${service}client&lt;/span&gt;&lt;/code&gt;, test fixtures, and other
helpers and utils.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova support for using keystoneauth1 config options for Cinder.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/655985/"&gt;https://review.opendev.org/#/c/655985/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Existing unit tests will need to be updated to assert calls to the SDK instead
of the client. In cases where the client call was mocked, this should be a
matter of swapping out that mock and its assertions. No significant additional
unit testing should be required.&lt;/p&gt;
&lt;p&gt;Existing functional test cases should be adequate. Changes may be required in
fixtures and other framework.&lt;/p&gt;
&lt;p&gt;Existing integration tests should continue to function seamlessly. This will be
the litmus test of success.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="sdk-in-nova" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/643664/"&gt;https://review.opendev.org/#/c/643664/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="sdk-for-ironic" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/642899/"&gt;https://review.opendev.org/#/c/642899/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="sdk-for-placement" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/656023/"&gt;https://review.opendev.org/#/c/656023/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005810.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005810.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/openstacksdk/latest/user/config/configuration.html"&gt;https://docs.openstack.org/openstacksdk/latest/user/config/configuration.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-sdks/%23openstack-sdks.2019-05-20.log.html#t2019-05-20T13:48:07"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-sdks/%23openstack-sdks.2019-05-20.log.html#t2019-05-20T13:48:07&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/662881/"&gt;https://review.opendev.org/#/c/662881/&lt;/a&gt;&lt;/p&gt;
&lt;section id="items-implemented-in-train"&gt;
&lt;h3&gt;Items Implemented In Train&lt;/h3&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/676926/"&gt;https://review.opendev.org/#/c/676926/&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/642899/"&gt;https://review.opendev.org/#/c/642899/&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/656027/"&gt;https://review.opendev.org/#/c/656027/&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/656028/"&gt;https://review.opendev.org/#/c/656028/&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/659690/"&gt;https://review.opendev.org/#/c/659690/&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/680649/"&gt;https://review.opendev.org/#/c/680649/&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/676837/"&gt;https://review.opendev.org/#/c/676837/&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced, Partially Implemented&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reintroduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 08 Nov 2024 00:00:00 </pubDate></item><item><title>Nova - Cyborg Interaction</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/nova-cyborg-interaction.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-cyborg-interaction"&gt;https://blueprints.launchpad.net/nova/+spec/nova-cyborg-interaction&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification describes the Nova - Cyborg interaction needed to create
and manage instances with accelerators, and the changes needed in Nova to
accomplish that.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="scope"&gt;
&lt;h3&gt;Scope&lt;/h3&gt;
&lt;p&gt;Nova and Cyborg need to interact in many areas for handling instances with
accelerators. While this spec covers the gamut, specific areas are covered in
detail in other specs. We list all the areas below, identify which specific
parts are covered by other specs, and describe what is covered in this spec.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Representation: Cyborg shall represent devices as nested resource providers
under the compute node (except possibly for disaggregated servers),
accelerator types as resource classes and accelerators as inventory in
Placement. The properties needed for scheduling are represented as traits.
This is specified by &lt;a class="footnote-reference brackets" href="#cy-nova-place" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This spec does not
dwell on this topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discovery and Updates: Among the devices discovered in a host, Cyborg
intends to claim only those that are not included under the PCI Whitelisting
mechanism. Cyborg shall update Placement in a way that is compatible with
the virt driver’s update of Placement. These aspects are addressed in
sections &lt;a class="reference internal" href="#coexistence-with-pci-whitelists"&gt;Coexistence with PCI whitelists&lt;/a&gt; and &lt;a class="reference internal" href="#placement-update"&gt;Placement update&lt;/a&gt;
respectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User requests for accelerators: Users usually request compute resources via
flavors. However, since the requests for devices may be highly varied,
placing them in flavors may result in flavor explosion. We avoid that by
expressing device requests in a device profile &lt;a class="footnote-reference brackets" href="#dev-prof" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; . The
relationship between device profiles and flavors is explored in Section
&lt;a class="reference internal" href="#user-requests"&gt;User requests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When an instance creation (boot) request is made, the contents of a device
profile shall be translated to request groups in the request spec; the
syntax in request groups is covered in Section &lt;a class="reference internal" href="#updating-the-request-spec"&gt;Updating the Request Spec&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance scheduling: Nova shall use the Placement data populated by Cyborg
to schedule instances. This spec does not dwell on this topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assignment of accelerators: We introduce the concept of Accelerator Request
objects in Section &lt;a class="reference internal" href="#accelerator-requests"&gt;Accelerator Requests&lt;/a&gt;.  The workflow to create and use
them is summarized in Section &lt;a class="reference internal" href="#nova-changes-for-assignment-workflow"&gt;Nova changes for Assignment workflow&lt;/a&gt;. The
same section also highlights the Nova changes needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance operations: The behavior with respect to accelerators for all
standard instance operations are defined in &lt;a class="footnote-reference brackets" href="#inst-ops" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.
This spec does not dwell on this topic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A user requests an instance with one or more accelerators of different
types assigned to it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An operator may provide users with both Device as a Service or
Accelerated Function as a Service in the same cluster (see
&lt;a class="footnote-reference brackets" href="#cy-nova-place" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following use cases are not addressed in this release but are of
long term interest:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A user requests to add one or more accelerators to an existing instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live migration with accelerators.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="coexistence-with-pci-whitelists"&gt;
&lt;h3&gt;Coexistence with PCI whitelists&lt;/h3&gt;
&lt;p&gt;The operator tells Nova which PCI devices to claim and use by configuring the
PCI Whitelists mechanism. In addition, the operator installs Cyborg drivers in
compute nodes and configures/enables them. Those drivers may then discover and
report some PCI devices. The operator must ensure that both configurations
are compatible.&lt;/p&gt;
&lt;p&gt;Ideally, there should be a single way for the operator to identify which PCI
devices should be claimed by Nova and which by Cyborg. Until that is figured
out, the operator shall use Cyborg’s configuration file to specify which
Cyborg drivers are enabled. Since each driver claims specific PCI IDs, the
operator can and must ensure that none of these PCI IDs are included in Nova’s
PCI whitelist.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="placement-update"&gt;
&lt;h3&gt;Placement update&lt;/h3&gt;
&lt;p&gt;Cyborg shall call Placement API directly to represent devices and
accelerators. Some of the intended use cases for the API invocation are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create or delete child RPs under the compute node RP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create or delete custom RCs and custom traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Associate traits with RPs or remove such association.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update RP inventory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cyborg shall not modify the RPs created by any other component, such
as Nova virt drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="user-requests"&gt;
&lt;h3&gt;User requests&lt;/h3&gt;
&lt;p&gt;The user request for accelerators is encapsulated in a device profile
&lt;a class="footnote-reference brackets" href="#dev-prof" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, which is created and managed by the admin via the Cyborg API.&lt;/p&gt;
&lt;p&gt;A device profile may be viewed as a ‘flavor for devices’. Accordingly, the
instance request should include both a flavor and a device profile. However,
that requires a change to the Nova API for instance creation. To mitigate the
impact of such changes on users and operators, we propose to do this
in phases.&lt;/p&gt;
&lt;p&gt;In the initial phase, Nova API remains as today. The device profile is folded
into the flavor as an extra spec by the operator, as below:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="s1"&gt;'accel:device_profile=&amp;lt;profile_name&amp;gt;'&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Thus the standard Nova API can be used to create an instance with only the
flavor (without device profiles), like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;....&lt;/span&gt;  &lt;span class="c1"&gt;# instance creation&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the future, device profile may be used by itself to specify accelerator
resources for the instance creation API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="updating-the-request-spec"&gt;
&lt;h3&gt;Updating the Request Spec&lt;/h3&gt;
&lt;p&gt;When the user submits a request to create an instance, as described in Section
&lt;a class="reference internal" href="#user-requests"&gt;User requests&lt;/a&gt;, Nova needs to call a Cyborg API, to get back the resource
request groups in the device profile and merge them into the request spec.
(This is along the lines of the scheme proposed for Neutron
&lt;a class="footnote-reference brackets" href="#req-spec-groups" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.)&lt;/p&gt;
&lt;p id="cyborg-client-module"&gt;This call, like all the others that Nova would make to Cyborg APIs, is done
through a Keystone-based adapter that would locate the Cyborg service, similar
to the way Nova calls Placement. A new Cyborg client module shall be added to
Nova, to encapsulate such calls and to provide Cyborg-specific functionality.&lt;/p&gt;
&lt;p&gt;VM images in Glance may be associated with image properties (other than image
traits), such as bitstream/function IDs needed for that image. So, Nova should
pass the VM image UUID from the request spec to Cyborg. This is TBD.&lt;/p&gt;
&lt;p&gt;The groups in the device profile are numbered by Cyborg. The request groups
that are merged into the request spec are numbered by Nova. These numberings
would not be the same in general, i.e., the N-th device profile group may not
correspond to the N-th request group in the request spec.&lt;/p&gt;
&lt;p&gt;When the device profile request groups are added to other request groups in
the flavor, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_policy&lt;/span&gt;&lt;/code&gt; of the flavor shall govern the overall
semantics of all request groups.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="accelerator-requests"&gt;
&lt;h3&gt;Accelerator Requests&lt;/h3&gt;
&lt;p&gt;An accelerator request (ARQ) is an object that represents
the state of the request for an accelerator to be assigned to an instance.
The creation and management of ARQs are handled by Cyborg, and ARQs are
persisted in Cyborg database.&lt;/p&gt;
&lt;p&gt;An ARQ, by definition, represents a request for a single accelerator. The
device profile in the user request may have N request groups, each asking for
M accelerators; then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;N&lt;/span&gt; &lt;span class="pre"&gt;*&lt;/span&gt; &lt;span class="pre"&gt;M&lt;/span&gt;&lt;/code&gt; ARQs will be created for that device profile.&lt;/p&gt;
&lt;p&gt;When an ARQ is initially created by Cyborg, it is not yet associated with a
specific host name or a device resource provider. So it is said to be in an
unbound state. Subsequently, Nova calls Cyborg to bind the ARQ to a host name,
a device RP UUID and an instance UUID. If the instance fails to spawn, Nova
would unbind the ARQ without deleting it. On instance termination, Nova would
delete the ARQs after unbinding them.&lt;/p&gt;
&lt;p id="match-rp"&gt;Each ARQ needs to be matched to the specific RP in the allocation candidate
that Nova has chosen, before the ARQ is bound. The current Nova code maps
request groups to RPs, while the Cyborg client module in Nova
(&lt;a class="reference internal" href="#cyborg-client-module"&gt;cyborg-client-module&lt;/a&gt;) matches ARQs to request groups. The matching is
done using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt; field in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; object
as below:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The order of request groups in a device profile is not significant, but it
is preserved by Cyborg. Thus, each device profile request group has a unique
index.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the device profile request groups returned by Cyborg are added to the
request spec, the requester_id field is set to ‘device_profile_&amp;lt;N&amp;gt;’ for the
N-th device profile request group (starting from zero). The device profile
name need not be included here because there is only one device profile per
request spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When Cyborg creates an ARQ for a device profile, it embeds the device
profile request group index in the ARQ before returning it to Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The matching is done in two steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each ARQ is mapped to a specific request group in the request spec using
the requester_id field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each request group is mapped to a specific RP using the same logic as the
Neutron bandwidth provider (&lt;a class="footnote-reference brackets" href="#map-rg-to-rp" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="nova-changes-for-assignment-workflow"&gt;
&lt;h3&gt;Nova changes for Assignment workflow&lt;/h3&gt;
&lt;p&gt;This section summarizes the workflow details for Phase 1. The changes needed
in Nova are marked with NEW.&lt;/p&gt;
&lt;p&gt;NEW: A Cyborg client module is added to nova (&lt;a class="reference internal" href="#cyborg-client-module"&gt;cyborg-client-module&lt;/a&gt;). All
Cyborg API calls are routed through that.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;The Nova API server receives a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API request with a flavor
that includes a device profile name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova API server calls the Cyborg API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/v2/device_profiles?name=$device_profile_name&lt;/span&gt;&lt;/code&gt; and gets back the device
profile. The request groups in that device profile are added to the
request spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Nova scheduler invokes Placement and gets a list of allocation
candidates. It selects one of those candidates and makes
claim(s) in Placement. The Nova conductor then sends a RPC message
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;build_and_run_instances&lt;/span&gt;&lt;/code&gt; to the Nova compute manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: Nova compute manager calls the Cyborg API
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/v2/accelerator_requests&lt;/span&gt;&lt;/code&gt; with the device profile name. Cyborg
creates a set of unbound ARQs for that device profile and returns them to
Nova. (The call may originate from Nova conductor or the compute manager;
that will be settled in code review.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Cyborg client in Nova matches each ARQ to the resource provider
picked for that accelerator. See &lt;a class="reference internal" href="#match-rp"&gt;match-rp&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova compute manager calls the Cyborg API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;
&lt;span class="pre"&gt;/v2/accelerator_requests&lt;/span&gt;&lt;/code&gt; to bind the ARQ with the host name, device’s RP
UUID and instance UUID. This is an asynchronous call which prepares or
reconfigures the device in the background.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: Cyborg, on completion of the bindings (successfully or otherwise),
calls Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/os-server-external-events&lt;/span&gt;&lt;/code&gt; API with:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
   "events": [
      { "name": "accelerator-requests-bound",
        "tag": $device_profile_name,
        "server_uuid": $instance_uuid,
        "status": "completed" # or "failed"
      },
      ...
   ]
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova compute manager waits for the notification, subject to the
timeout mentioned in Section &lt;a class="reference internal" href="#other-deployer-impact"&gt;Other deployer impact&lt;/a&gt;. It then calls
the Cyborg REST API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/v2/accelerator_requests?instance=&amp;lt;uuid&amp;gt;&amp;amp;bind_state=resolved&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova virt driver uses the attach handles returned from the Cyborg
call to compose PCI passthrough devices into the VM’s definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: If there is any error after binding has been initiated, Nova
must unbind the relevant ARQs by calling Cyborg API. It may then retry on
another host or delete the (unbound) ARQs for the instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This flow is captured by the following sequence diagram, in which the Nova
conductor and scheduler are together represented as the Nova controller.&lt;/p&gt;
&lt;img alt="../../../_images/nova-cyborg-interaction1.svg" src="../../../_images/nova-cyborg-interaction1.svg"/&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;It is possible to have an external agent create ARQs from device profiles
by calling Cyborg, and then feed those pre-created ARQs to the Nova instance
creation API, analogous to Neutron ports. We do not take that approach yet
because it requires changes to Nova instance creation API.&lt;/p&gt;
&lt;p&gt;It is possible to have the Nova virt driver poll for the Cyborg ARQ binding
completion. That is not preferable, partly because that is not the pattern of
interaction with other services like Neutron.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None. A new extra_spec key &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accel:device_profile_name&lt;/span&gt;&lt;/code&gt; is added to
the flavor, but no API is modified.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Nova may choose to add additional notifications for Cyborg API calls.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The extra calls to Cyborg REST API may potentially impact Nova
conductor/scheduler throughput. This has been mitigated by making some
critical Cyborg operations as asynchronous tasks.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The deployer needs to set up the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;clouds.yaml&lt;/span&gt;&lt;/code&gt; file so that Nova
can call the Cyborg REST API.&lt;/p&gt;
&lt;p&gt;The deployer needs to configure a new tunable in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-cpu.conf&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arq_binding_timeout&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;
  &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Cyborg&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;ARQ&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;fatal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;aborted&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;300.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The resource classes FPGA and PGPU have already been standardized. But,
as new device types are proposed, they will be represented as custom
RCs to begin with, but may get standardized later. Such standardization
requires changes to os-resource-classes.&lt;/p&gt;
&lt;p&gt;For end-to-end testing with tempest, Cyborg shall provide a fake driver
which returns attach handles of type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TEST_PCI&lt;/span&gt;&lt;/code&gt;. The Nova virt driver
should ignore such attach handles, and create VMs as if such ARQs did
not exist.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Sundar Nadathur&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;efried&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;See the steps marked NEW in &lt;a class="reference internal" href="#nova-changes-for-assignment-workflow"&gt;Nova changes for Assignment workflow&lt;/a&gt; section.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;There need to be unit tests and functional tests for the Nova changes.
Specifically, there needs to be a functional test fixture that mocks the
Cyborg API calls.&lt;/p&gt;
&lt;p&gt;There need to be tempest tests for the end-to-end flow, including failure
modes. The tempest tests should be targeted at a fake driver (in addition to
real hardware, if any) and tied to the Nova Zuul gate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Device profile creation needs to be documented in Cyborg, as noted in
&lt;a class="footnote-reference brackets" href="#dev-prof" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The need for operator to fold the device profile into the flavor needs to be
documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="cy-nova-place" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/603545/"&gt;Specification for Cyborg Nova Placement
interaction&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="dev-prof" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/602978"&gt;Device profiles specification&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="inst-ops" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/605237/"&gt;Specification for instance operations with accelerators&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="req-spec-groups" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/567267/"&gt;Store RequestGroup objects in RequestSpec&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="map-rg-to-rp" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/63380a6b494e0f0f220b67b197edec836f1c5a42/nova/objects/request_spec.py#L777"&gt;Map request groups to resource providers&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 08 Nov 2024 00:00:00 </pubDate></item><item><title>Per Process Healthcheck endpoints</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/per-process-healthchecks.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks"&gt;https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In many modern deployment frameworks, there is an expectation that
an application can expose a health-check endpoint so that the binary
status can be monitored. Nova currently does not provide a native way
to inspect the health of its binaries which doesn’t help cloud monitoring
and maintenance. While limited support exists for health checks via
Oslo middleware for our WSGI based API binaries, this blueprint seeks
to expose a local HTTP health-check endpoint to address this
feature gap consistently for all Nova components.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;To monitor the health of a Nova service today requires experience to
develop and implement a series of external heuristics to infer the state
of the service binaries.&lt;/p&gt;
&lt;p&gt;This can be as simple as checking the service status for those with heartbeats
or can comprise monitoring log output via a watchdog and restarting
the service if no output is detected after a protracted period.
Processing the logs for known error messages and executing a remediation script
or other methods that are easy to do incorrectly are also common.&lt;/p&gt;
&lt;p&gt;This is also quite unfriendly to new Nova users who have not gained enough
experience with operating Nova to know what warning signs they should look
for such as inability to connect to the message bus. Nova developers however
do know what some of the important health indicators are and can expose
those as a local health-check endpoint that operators can use instead.&lt;/p&gt;
&lt;p&gt;The existing Oslo middleware does not address this problem statement because:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;It can only be used by the API and metadata binaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The middleware does not tell you the service is alive if its hosted by a
WSGI server like Apache since the middleware is executed independently from
the WSGI application. i.e. the middleware can pass while the nova-api can’t
connect to the DB and is otherwise broken.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Oslo middleware in detailed mode leaks info about the host Python
kernel, Python version and hostname which can be used to determine in the
host is vulnerable to CVEs which means it should never be exposed to the
Internet. e.g.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Linux-5.15.2-xanmod1-tt-x86_64-with-glibc2.2.5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;python_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3.8.12 (default, Aug 30 2021, 16:42:10) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[GCC 10.3.0]'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want a simple REST endpoint I can consume to know
if a Nova process is healthy.&lt;/p&gt;
&lt;p&gt;As an operator I want this health check to not impact the performance of the
service so it can be queried frequently at short intervals.&lt;/p&gt;
&lt;p&gt;As a deployment tool implementer, I want the health check to be local with no
dependencies on other hosts or services to function so I can integrate it with
service managers such as systemd or a container runtime like Docker.&lt;/p&gt;
&lt;p&gt;As a packager, I would like the use of the health check endpoints to not
require special clients or packages to consume them. cURL, socat, or netcat
should be all that is required to connect to the health check and retrieve the
service status.&lt;/p&gt;
&lt;p&gt;As an operator I would like to be able to use health-check of the Nova API and
metadata services to manage the membership of endpoints in my load-balancer
or reverse proxy automatically.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="definitions"&gt;
&lt;h3&gt;Definitions&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TTL&lt;/span&gt;&lt;/code&gt;: The time interval for which a health check item is valid.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;: all health indicators are passing and their TTLs have not expired.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;: any health indicator has an expired TTL or where there is
a partial transient failure.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;: any health indicator is reporting an error or all TTLs are expired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="warn-vs-fail"&gt;
&lt;h3&gt;Warn vs fail&lt;/h3&gt;
&lt;p&gt;In general if any of the health check indicators are failing then the service
should be reported as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; however if the specific error condition is
recoverable or only a partial failure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state can and should be
used.&lt;/p&gt;
&lt;p&gt;An example of this is a service that has lost a connection to the message bus.
When the connection is lost it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state, if the first
attempt to reconnect fails it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state. Transient
failure should be considered warning but persistent errors should be escalated
to failures.&lt;/p&gt;
&lt;p&gt;In many cases external management systems will treat &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; as
equivalent and raise an alarm or restart the service. While this spec does
not specify how you should recover from a degraded state, it is
important to include a human readable description of why the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state was entered.&lt;/p&gt;
&lt;p&gt;Services in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state are still considered healthy in most cases but
they may be about to fail soon or be partially degraded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;Code changes&lt;/h3&gt;
&lt;p&gt;A new top-level Nova health check module will be created to encapsulate the
common code and data structure required to implement this feature.&lt;/p&gt;
&lt;p&gt;A new health check manager class will be introduced which will maintain the
health-check state and all functions related to retrieving, updating and
summarizing that state.&lt;/p&gt;
&lt;p&gt;The health check manager will be responsible for creating the health check
endpoint when it is enabled in the nova.conf and exposing the health check
over HTTP.&lt;/p&gt;
&lt;p&gt;The initial implementation will support HTTP over TCP with optional support for
UNIX domain sockets as a more secure alternative to be added later.
The HTTP endpoint in both cases will be unauthenticated and the response will
be in JSON format.&lt;/p&gt;
&lt;p&gt;A new HealthcheckStausItem data class will be introduced to store an
individual health check data-point. The HealtcheckStatusItem will contain
the name of the health check, its status, the time it was recorded,
and an optional output string that should be populated if the
status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A new decorator will be introduced that will automatically retrieve the
reference to the healthcheck manager from the Nova context object and update
the result based on whether the function decorated raises an exception or not.
The exception list and healthcheck item name will be specifiable.&lt;/p&gt;
&lt;p&gt;The decorator will accept the name of the health check as a positional argument
and include the exception message as the output of the health check on failure.
Note that the decorator will only support the pass or fail status for
simplicity; where warn is appropriate a manual check should be written.
If multiple functions act as indicators of the same capability the same name
should be used.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_other_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default all exceptions will be caught and re-raised by the decorator.&lt;/p&gt;
&lt;p&gt;The new REST health check endpoint exposed by this spec will initially only
support one URL path &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt;. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; endpoint will include a
&lt;cite&gt;Cache-Control: max-age=&amp;lt;ttl&amp;gt;&lt;/cite&gt; header as part of its response which can
optionally be consumed by the client.&lt;/p&gt;
&lt;p&gt;The endpoint may also implement a simple incrementing etag at a later date
once the initial implementation is complete, if required.
Initially adding an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; is not provided as the response is expected to be
small and cheap to query, so etags do not actually provide much benefit form
a performance perspective.&lt;/p&gt;
&lt;p&gt;If implemented, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; will be incremented whenever the service state
changes and will reset to 0 when the service is restarted.&lt;/p&gt;
&lt;p&gt;Additional URL paths may be supported in the future, for example to retrieve
the running configuration or trigger the generation of Guru Meditation Reports
or enable debug logging. However, any endpoint beyond &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; is out of
scope of this spec. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; is not used for health check response to facilitate
additional paths in the future.&lt;/p&gt;
&lt;section id="example-output"&gt;
&lt;h4&gt;Example output&lt;/h4&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"e3c22423-cd7a-47dc-b6e9-e18d1a8b3bdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"api_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="n"&gt;Sevice&lt;/span&gt; &lt;span class="n"&gt;Unavailable&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0a47dceb-11b1-4d94-8b9c-927d998be320"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-compute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"hypervisor"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
             &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:05:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s2"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Libvirt Error: ..."&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of maintaining the state of the process in a data structure and
returning the cached state we, could implement the health check as a series of
active probes such as checking the DB schema version to ensure we can access
it or making a ping RPC call to the cell conductor or our own services RPC
endpoint.&lt;/p&gt;
&lt;p&gt;While this approach has some advantages it will have a negative performance
impact if the health-check is queried frequently or in a large deployment where
infrequent queries may still degrade the DB and message bus performance due to
the scale of the deployment.&lt;/p&gt;
&lt;p&gt;This spec initially suggested using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OK&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Degraded&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Faulty&lt;/span&gt;&lt;/code&gt; as the
values for the status field. These were updated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; to align with the draft IETF RFC for health check response format for
HTTP APIs &lt;a class="reference external" href="https://tools.ietf.org/id/draft-inadarei-api-health-check-06.html"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The Nova context object will be extended to store a reference to the
health check manager.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While this change will expose a new REST API endpoint it will not be
part of the existing Nova API.&lt;/p&gt;
&lt;p&gt;In the Nova API the /health check route will not initially be used to allow
those that already enable the Oslo middleware to continue to do so.
In a future release Nova reserves the right to add a /health check endpoint
that may or may not correspond to the response format defined in Oslo.
A translation between the Oslo response format and the health check module
may be provided in the future but it is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The new health check endpoint will be disabled by default.
When enabled it will not provide any authentication or explicit access control.
The documentation will detail that when enabled, the TCP endpoint should be
bound to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;localhost&lt;/span&gt;&lt;/code&gt; and that file system permission should be used to secure
the UNIX socket.&lt;/p&gt;
&lt;p&gt;The TCP configuration option will not prevent binding it to a routable IP if
the operator chooses to do so. The intent is that the data contained in the
endpoint will be non-privileged however it may contain hostnames/FQDNs or other
infrastructure information such as service UUIDs, so it should not be
accessible from the Internet.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While the health checks will use the ability to send notification as an input
to determine the health of the system, this spec will not introduce any new
notifications and as such it will not impact the Notification subsystem in
Nova. New notifications are not added as this would incur a performance
overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;At present, it is not planned to extend the Nova client or the unified client
to query the new endpoint. cURL, socat, or any other UNIX socket or TCP HTTP
client can be used to invoke the endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;We expect there to be little or no performance impact as we will be taking a
minimally invasive approach to add health indicators to key functions
which will be cached in memory. While this will slightly increase memory usage
there is no expected impact on system performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new config section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;healthcheck&lt;/span&gt;&lt;/code&gt; will be added in the nova.conf&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uri&lt;/span&gt;&lt;/code&gt; config option will be introduced to enable the health check
functionality. The config option will be a string opt that supports a
comma-separated list of URIs with the following format&lt;/p&gt;
&lt;p&gt;uri=&amp;lt;scheme&amp;gt;://[host:port|path],&amp;lt;scheme&amp;gt;://[host:port|path]&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The URI should be limited to the following characters &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[a-zA-Z0-9_-]&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;,&lt;/span&gt;&lt;/code&gt; is reserved as a separation character, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; may only be used in IPv4
addresses, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt; is reserved for port separation unless the address is an
IPv6 address. IPv6 addresses must be enclosed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[&lt;/span&gt;&lt;/code&gt; and  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;]&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; may
be used with the UNIX protocol however relative paths are not supported.
These constraints and the parsing of the URI will be enforced and provided by
the RFC3986 lib &lt;a class="reference external" href="https://pypi.org/project/rfc3986/"&gt;https://pypi.org/project/rfc3986/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt; IntOpt will be added with a default value of 300 seconds.
If set to 0, the time to live of a health check item will be infinite.
If the TTL expires, the state will be considered unknown and the healthcheck
item will be discarded.&lt;/p&gt;
&lt;p&gt;A cache_control IntOpt will be provided to set the max-age value in the
cache_control header. By default it will have the same max-age as the TTL
config option. Setting this to 0 will disable the reporting of the header.
Setting this to -1 will report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Cache-Control:&lt;/span&gt; &lt;span class="pre"&gt;no-cache&lt;/span&gt;&lt;/code&gt;.
Any other positive integer value will be used as the max-age.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers should be aware of the new decorator and consider whether it should
be added to more functions, if that function is an indicator of the system’s
health. Failures due to interactions with external systems such as Neutron port
binding external events should be handled with caution. While failure to
receive a port binding event will likely result in the failure to boot a VM, it
should not be used as a health indicator for the nova-compute agent. This is
because such a failure may be due to a failure in Neutron, not Nova. As such,
other operations such as VM snapshot may be unaffected and the Nova compute
service may be otherwise healthy. Any failure to connect to a non-OpenStack
service such as the message bus, hypervisor, or database should be treated as a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; health indicator if it prevents the Nova binary from
functioning correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce decorator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend context object to store a reference to health check manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose TCP endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose UNIX socket endpoint support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested entirely with unit and functional tests, however,
Devstack will be extended to expose the endpoint and use it to determine
whether the Nova services have started.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The config options will be documented in the config reference
and a release note will be added for the feature.&lt;/p&gt;
&lt;p&gt;A new health check section will be added to the admin docs describing
the current response format and how to enable the feature and its intended
usage. This document should be evolved whenever the format changes or
new functionality is added beyond the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Yoga PTG topic:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415"&gt;https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 04 Nov 2024 00:00:00 </pubDate></item><item><title>libvirt driver launching instances with memory encryption by AMD SEV-ES</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/approved/amd-sev-es-libvirt-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/amd-sev-es-libvirt-support"&gt;https://blueprints.launchpad.net/nova/+spec/amd-sev-es-libvirt-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes work required in order to extend the existing libvirt driver
feature to launch AMD SEV-encrypted instances, to support also using AMD
SEV-ES, which is the extended version of AMD SEV, as memory encryption
mechanism.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current libvirt driver supports launching instances with memory encryption by
&lt;a class="reference external" href="https://developer.amd.com/sev/"&gt;AMD’s SEV (Secure Encrypted Virtualization) technology&lt;/a&gt;. However the current implementation supports
only AMD SEV, and does not support new versions. For exmaple SEV-ES also
encrypts all CPU register contents when a VM stops running, to achieve more
complete protection of VM data, but users can’t leverage these features because
of this limitation.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;At the time or writing AMD already released CPUs which supports SEV-SNP, but
the required hypervisor features to use SEV-SNP are not yet merged into
the underlying components(kernel, QEMU, libvirt and ovmf). So in this spec
we focus on SEV-ES. We attempt to keep the proposal as much compatible with
SEV-SNP as possible, based on the implementations published by AMD.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud administrator, in order that my users can have more confidence
in the security of their running instances, I want to provide an image with
the specific properties or a flavor with the specific extra specs which will
allow users to boot instances to ensure that their instances run on
an SEV-ES-capable compute host with SEV-ES encryption, instead of SEV
encryption, enabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud user, in order to reduce data leakage risks further, I want to
be able to boot VM instances with SEV-ES functionality, instead of SEV
functionality, enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose extending the existing implementation to support launching instances
with SEV functionality.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV-ES capabilities, which checks the following items.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The presence of the following XML in the response from a libvirt
&lt;a class="reference external" href="https://libvirt.org/html/libvirt-libvirt-domain.html#virConnectGetDomainCapabilities"&gt;virConnectGetDomainCapabilities()&lt;/a&gt;
API call &lt;a class="reference external" href="https://libvirt.org/git/?p=libvirt.git;a=commit;h=6688393c6b222b5d7cba238f21d55134611ede9c"&gt;indicates that both QEMU and the AMD Secure Processor
(AMD-SP) support SEV functionality&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt; &lt;span class="n"&gt;supported&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Also the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxESGuests&lt;/span&gt;&lt;/code&gt; field should be present and its value should be
a positive (non-zero) value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/sys/module/kvm_amd/parameters/sev_es&lt;/span&gt;&lt;/code&gt; should have the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Y&lt;/span&gt;&lt;/code&gt;
to indicate that the kernel has SEV capabilities enabled.  This
should be readable by any user (i.e. even non-root).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check QEMU version to determine whether the available QEMU binary supports
SEV-ES.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait to os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the libvirt driver &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update the ProviderTree object&lt;/a&gt;
with the correct inventory for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource class
for both SEV and SEV-ES. To represent the slots dedicated for SEV and SEV-ES,
nested resource providers are created per-model:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+------------+&lt;/span&gt;     &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt; &lt;span class="o"&gt;+--+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ES&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The SEV RP is named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;nodename&amp;gt;_amd_sev&lt;/span&gt;&lt;/code&gt; and the SEV-ES RP is named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;nodename&amp;gt;_amd_sev_es&lt;/span&gt;&lt;/code&gt;, so that the RP names are unique in the cluster.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV and SEV-ES have separate limits of guest numbers, because ASIDs are
allocated for ES guests and non-ES guests exclusively, from the total
ASIDs available. Minimum ASID for SEV (non-ES) guests, which is
effectively same as maxumum ASID for ES guests, should be configured in
BIOS (or UEFI) to use SEV-ES. A new validation to detect insufficient
ASIDs may be implemented.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV-SNP uses the same ASID pool for ES by default when cyphertext hiding
is not requested, and the new trait (such as HW_CPU_AMD_SEV_SNP) may be
added to the existing SEV-ES RP when SEV-SNP support is added with
a separate SEV-SNP RP with the trait corrsponding to the cyphertext hiding
feature:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+------------+&lt;/span&gt;     &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt; &lt;span class="o"&gt;+--+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ES&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_SNP&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+-----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SNP&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_SNP_CH&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+----+&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+----+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that SEV-SNP support is out of the current scope and this design
needs further dicsussion when the support is actually implemented. It is
described here to explain the potential plan to extend the RP structure
in the future.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model&lt;/span&gt;&lt;/code&gt; parameter in flavor
extra specs, and a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model&lt;/span&gt;&lt;/code&gt; image property. When
either of these is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt; along with the parameter/propery to
enable memory encryption, it would be internally translated to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV_ES=required&lt;/span&gt;&lt;/code&gt; which would be added to the flavor extra
specs in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; object. If these new model parameter/property is
absent or set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev&lt;/span&gt;&lt;/code&gt; then it would be translated to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV=required&lt;/span&gt;&lt;/code&gt;. If conflicting models are requested by
the instance flavor and the instance image (for example the flavor has
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model=amd-sev&lt;/span&gt;&lt;/code&gt; but the image has
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model=amd-sev-es&lt;/span&gt;&lt;/code&gt;) then the request is rejected. Also
the request should be rejected when memory encryption is not requested but
a memory encryption model is requested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the libvirt driver to include extra XML in the guest’s domain
definition when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model&lt;/span&gt;&lt;/code&gt; parameter in flavor extra
spec or the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model&lt;/span&gt;&lt;/code&gt; image property is present and
is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt;. The extra XML is mostly similar to the one used in
SEV, but its guest policy field needs the SEV-ES bit (bit 2) enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Guest attestation is currently out of our scope. Because &lt;a class="reference external" href="https://libvirt.org/kbase/launch_security_sev.html#guest-attestation-for-sev-sev-es-from-a-trusted-host"&gt;the existing
feature for guest attestation&lt;/a&gt;
heavily depends on hypervisor features and is not suitable for confidential
computing use case where users do not trust hypervisors. We aim to implement
the guest attestation feature once SEV-SNP is generally available, because
SEV-SNP provides a better mechanism for guest attestation, using the special
device presented to guest machines to obtain attestation reports.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The end user will harness SEV-ES through the existing mechanisms of resources
in flavor extra specs and image properties.&lt;/p&gt;
&lt;p&gt;Also &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html#impermanent-limitations"&gt;the limitations of AMD SEV-encrypted guest&lt;/a&gt;
are applied when SEV-ES is used.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No performance impact on nova is anticipated.&lt;/p&gt;
&lt;p&gt;Performance impact for the other parts are same as the existing SEV support
feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In order for users to be able to use SEV-ES, the operator will need to
perform the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy SEV-ES-capable hardware as nova compute hosts.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;AMD EPYC 7xx2 (Rome) or later&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set minimum ASID for SEV (non-ES) guests in BIOS (or UEFI) to a value greater
than 0.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If SEV-enabled instancs are already launched in the compute node, enough
ASIDs should be reserved for SEV.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that they have an appropriately configured software stack, so
that the various layers are all SEV-ES ready:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;kernel &amp;gt;= 4.16&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;= 6.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libvirt &amp;gt;= 8.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ovmf &amp;gt;= commit 7f0b28415cb4 2020-08-12&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV-ES enabled guests can be launched by libvirt &amp;gt;= 4.5, but detection of
maximum number of SEV-ES guests via domain capability API requires libvirt
&amp;gt;= 8.0.0 .&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A cloud administrator will need to define SEV-ES-enabled flavors as described
above, unless it is sufficient for users to define SEV-ES-enabled images.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;[libvirt] num_memory_encrypted_guests&lt;/cite&gt; option is effective only for SEV,
but a new option for SEV-ES is NOT added. Instead, the detection capability in
libvirt is required to use SEV-ES. The &lt;cite&gt;num_memory_encrypted_guests&lt;/cite&gt; option
will be deprecated to reduce complexity.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kajinamit (irc: tkajinam)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait for os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV-ES capabilities as detailed above and reshaping
of existing MEMO_ENCRYPTION_CONTEXT resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property to ImageMeta object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update scheduler util to request &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property or
the equivalent flavor extra spec is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update libvirt driver to set the SEV-ES policy bit when the property is
present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update image property schema in glance to validate the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unit tests and functional tests should be added according to new logic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="future-work"&gt;
&lt;h3&gt;Future work&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Special hardware which supports SEV-ES for development, testing, and CI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recent versions of the hypervisor software stack which all support
SEV-ES, as detailed in &lt;a class="reference internal" href="#other-deployer-impact"&gt;Other deployer impact&lt;/a&gt; above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fakelibvirt&lt;/span&gt;&lt;/code&gt; test driver will need adaptation to emulate
SEV-ES-capable hardware.&lt;/p&gt;
&lt;p&gt;Corresponding unit/functional tests will need to be extended or added
to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;detection of SEV-ES-capable hardware and software, e.g. perhaps as an
extension of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.functional.libvirt.test_report_cpu_traits.LibvirtReportTraitsTests&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the use of a trait to include extra SEV-specific libvirt domain XML
configuration, e.g. within
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.unit.virt.libvirt.test_config&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the entry in &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/support-matrix.html"&gt;the Feature Support Matrix&lt;/a&gt;,
to explain now AMD SEV-ES is supported in addition to AMD SEV.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the existing &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html"&gt;AMD SEV&lt;/a&gt; guide to include
information about SEV-ES.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other non-nova documentation should be updated too:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/os-traits/latest/"&gt;documentation for os-traits&lt;/a&gt; should be extended
where appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/sev"&gt;AMD SEV landing page&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/55766.PDF"&gt;AMD SEV-KM API Specification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/AMDESE/AMDSEV/"&gt;AMD SEV github repository containing examples and tools&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://events17.linuxfoundation.org/sites/events/files/slides/AMD%20SEV-ES.pdf"&gt;Slides from the 2017 Linux Security Summit describing SEV and
preliminary performance results&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#sev"&gt;libvirt’s SEV options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 10 Sep 2024 00:00:00 </pubDate></item><item><title>libvit driver launching instances with stateless firmware</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/implemented/libvirt-stateless-firmware.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-stateless-firmware"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-stateless-firmware&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since v8.6.0, libvirt allows launching instance with stateless firmware, which
disables the potential attack surface from hypervisor. This work aims to
introduce the required feature to allow users to use this feature.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Libvirt v8.6.0 introduced the new feature to launch instance with stateless
firmware. When an instance is launched with this feature enabled along with
UEFI, the instance uses a ready-only firmware image without NVRAM file. This
feature is useful for confidential computing use case, because it prevents
injection into firmware vars from hypervisor. It also allows more complete
measurement of elements involved in the boot chain of the instance which is
the key requirement of remote attestation. This is described in
&lt;a class="reference external" href="https://libvirt.org/kbase/launch_security_sev.html"&gt;the libvirt guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However this libvirt feature can’t be enabled in instances launched by current
nova, because nova does not set the stateless option. Also nova always injects
nvram file into libvirt domain XML.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud administrator, in order that my users can have more confidence in
the security of their running instances, I want to allow my users to
enforce stateless firmware for their instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user, I want to prevent risk caused by firmware variables injected by
hypevisor, for instances which load very confidential data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose adding a new image property to request stateless firmwre, so that
users can create their instance with stateless firmware.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_STATELESS_FIRMWARE&lt;/span&gt;&lt;/code&gt; trait to os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make libvirt driver check the current version of libvirt and report
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;supports_stateless_firmware&lt;/span&gt;&lt;/code&gt; capability when the version is equal or
newer than v8.6.0. This capability should be mapped to
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_STATELESS_FIRMWARE&lt;/span&gt;&lt;/code&gt; trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_firmware_stateless&lt;/span&gt;&lt;/code&gt; image property, which accept boolean
values and is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;false&lt;/span&gt;&lt;/code&gt; by default. If the property is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; then
nova translate it to requiring the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_STATELESS_FIRMWARE&lt;/span&gt;&lt;/code&gt;
trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the libvirt driver to adds the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stateless&lt;/span&gt;&lt;/code&gt; option to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;loader&lt;/span&gt;&lt;/code&gt;
element of libvirt domain XML and skip injecting nvram file, if instance
metadata of the instance contains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_firmware_stateless&lt;/span&gt;&lt;/code&gt; property set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new trait and new image property will be used to present availability and
request of stateless firmware feature in libvirt.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The end user will be able to use statless firmware for their instances through
the existing image property mechanism.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In order for users to be able to use this feature, the operator will need to
deploy libvirt v8.6.0 or later in the deployment.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kajinamit (irc: tkajinam)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_STATELESS_FIRMWARE&lt;/span&gt;&lt;/code&gt; trait to os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make libvirt driver check libvirt version and present availability of
stateless firmware in compute node capabilities, as
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_STATELESS_FIRMWARE&lt;/span&gt;&lt;/code&gt; trait, based on the detected
version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_firmware_stateless&lt;/span&gt;&lt;/code&gt; image property to the ImageMeta
object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update scheduler util to require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_STATELESS_FIRMWARE&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_firmware_stateless&lt;/span&gt;&lt;/code&gt; property in instance image
properties is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make libvirt driver set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stateless="yes"&lt;/span&gt;&lt;/code&gt; in the loder element when
instance image properties contains the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_firmware_stateless&lt;/span&gt;&lt;/code&gt;
property set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update image property schema in glance to validate
the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_firmware_stateless&lt;/span&gt;&lt;/code&gt; property.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unit tests and functional tests should be added according to new logic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="future-work"&gt;
&lt;h3&gt;Future work&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Libvirt v8.6.0 or later.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fakelibvirt&lt;/span&gt;&lt;/code&gt; test driver will need adaptation to emulate libvirt older
than v8.6.0 and libvirt v8.6.0 or later.&lt;/p&gt;
&lt;p&gt;Corresponding unit/functional tests will need to be extended or added
to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;detection of the statless firmware support by libvirt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the use of a trait to include extra stateless loader option in domain XML
configuration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/support-matrix.html"&gt;the Feature Support Matrix&lt;/a&gt;, to
include stateless firmware support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the existing &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html"&gt;AMD SEV&lt;/a&gt; guide to include
information about stateless firmware.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#bios-bootloader"&gt;libvirt’s Domain XML format&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#sev"&gt;libvirt’s SEV options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 09 Sep 2024 00:00:00 </pubDate></item><item><title>OpenAPI Schemas</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/implemented/openapi.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/openapi"&gt;https://blueprints.launchpad.net/nova/+spec/openapi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to start documenting our APIs in an industry-standard,
machine-readable manner. Doing so opens up many opportunities for both
OpenStack developer and OpenStack users alike, notably the ability to both
auto-generate and auto-validate both client tooling and documentation alike. Of
the many API description languages available, OpenAPI (fka “Swagger”) appears
to be the one with both the largest developer mindshare and the one that would
be the best fit for OpenStack due to the existing tooling used in many
OpenStack services, thus we would opt to use this format.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The history of API description languages has been mainly a history of
half-baked ideas, unnecessary complication, and in general lots of failure.
This history has been reflected in OpenStack’s own history of attempting to
document APIs, starting with our early use of WADL through to our experiments
with Swagger 2.0 and RAML, leading to today’s use of our custom &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
project, built on reStructuredText and Sphinx.&lt;/p&gt;
&lt;p&gt;It is only in recent years that things have started to stabilise somewhat, with
the development of widely used API description languages like OpenAPI, RAML and
API Blueprint, as well as supporting SaaS tools such as Postman and Apigee.
OpenAPI in particular has seen broad adoption across multiple sectors, with
sites as varied as &lt;a class="reference external" href="https://blog.cloudflare.com/open-api-transition"&gt;CloudFlare&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/github/rest-api-description"&gt;GitHub&lt;/a&gt; providing OpenAPI schemas for
their APIs. OpenAPI has evolved significantly in recent years and now supports
a wide variety of API patterns including things like webhooks. Even more
beneficial for OpenStack, OpenAPI 3.1 is a full superset of JSON Schema meaning
we have the ability to re-use much of the validation we already have.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an end user, I would like to have access to machine-readable, fully
validated documentation for the APIs I will be interacting with.&lt;/p&gt;
&lt;p&gt;As an end user, I want statically viewable documentation hosted as part of the
existing docs site without requiring a running instance of Nova.&lt;/p&gt;
&lt;p&gt;As an SDK/client developer, I would like to be able to auto-generate bindings
and clients, promoting consistency and minimising the amount of manual work
needed to develop and maintain these.&lt;/p&gt;
&lt;p&gt;As a Nova developer, I would like to have a verified API specification that I
can use should I need to replace the web framework/libraries we use in the
event they are no longer maintained.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This effort can be broken into a number of distinct steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new decorator for removed APIs and actions&lt;/p&gt;
&lt;p&gt;We have a number of APIs and actions that no longer have backing code and
return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;410&lt;/span&gt; &lt;span class="pre"&gt;(Gone)&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;(Bad&lt;/span&gt; &lt;span class="pre"&gt;Request)&lt;/span&gt;&lt;/code&gt;, respectively. We
will not add schemas for these in the initial attempt at this so we need some
mechanism to indicate this. We will add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;removed&lt;/span&gt;&lt;/code&gt; decorator that will
highlight these removed APIs and indicate the version they were removed in
and the reason for their removal. We can later use this as a heuristic in our
tests to skip schema checks for these methods.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing request body and query string schemas&lt;/p&gt;
&lt;p&gt;There is already good coverage of both request bodies and query string
parameters but it is not complete. A list of incomplete schemas is given at
the end of this section. The additional schemas will merely validate what is
already allowed, which will mean extensive use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"additionalProperties":&lt;/span&gt;
&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; or empty schemas. Put another way, an API that currently ignores
unexpected request body fields or query string parameters will continue to
ignore them. We may wish to make these stricter, as we did for most APIs in
microversion 2.75, but that is a separate issue that should be addressed
separately.&lt;/p&gt;
&lt;p&gt;Once these specs are added, tests will be added to ensure all non-deprecated
and non-removed API resources have appropriate schemas.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;
&lt;p&gt;These will be sourced from existing OpenAPI schemas, currently published
at &lt;a class="reference external" href="https://github.com/gtema/openstack-openapi"&gt;github.com/gtema/openstack-openapi&lt;/a&gt;, from &lt;a class="reference external" href="https://github.com/openstack/tempest/tree/c0da6e843a/tempest/lib/api_schema/response/compute"&gt;Tempest’s API schemas&lt;/a&gt;,
and where necessary from new schemas auto-generated from JSON response bodies
generated in tests and manually modified handle things like enum values.&lt;/p&gt;
&lt;p&gt;Once these are added, tests will be added to ensure all non-deprecated and
non-removed API resources have appropriate response body schemas. In
addition, we will add a new configuration option that will control how we do
verification at the API layer, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. This will be an
enum value with three options:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Raise a HTTP 500 (Server Error) in the event that an API returns an
“invalid” response.&lt;/p&gt;
&lt;p&gt;This will be the default in CI i.e. for our unit, functional and
integration tests. This should not be used in production. The help text
of the option will indicate this and we will set the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;advanced&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Log a warning about an “invalid” response, prompting operations to file a
bug report against Nova.&lt;/p&gt;
&lt;p&gt;This will be initial (and likely forever) default in production.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ignore&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Disable API response body validation entirely. This is an escape hatch in
case we mess up.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The development of tooling required to gather these JSON Schema schemas and
generate an OpenAPI schema will not be developed inside Nova and is
therefore not covered by this spec. Nova will merely consume the resulting
tooling for use in documentation. It is intended that the same tool will be
usable across any OpenStack project that uses the same web frameworks
(in Nova’s case, WebOb + Routes).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The impact of middleware that modifies either the request or response will
not be accounted for in this change. This is because these are configurable
and they cannot be guaranteed to exist in a given deployment. Examples
include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sizelimit&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.middlware&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_token&lt;/span&gt;&lt;/code&gt; middleware from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;keystonemiddleware&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a different tool&lt;/p&gt;
&lt;p&gt;We could use a different tool than OpenAPI to publish our specs. In a manner
of speaking we already do this - albeit not in a machine-readable manner -
through our use of os-api-ref.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because OpenAPI is clearly the best tool for the
It is the most widely used API description language available today and
aligns well with our existing use of JSON Schema for API validation. While it
does not support OpenStack’s microversion API design pattern out-of-the-box,
previous experiments have demonstrated that it is extensible enough to add
this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain these specs out-of-tree&lt;/p&gt;
&lt;p&gt;We could use a separate repo to store and maintain specs for Nova and the
other OpenStack services.&lt;/p&gt;
&lt;p&gt;This idea has been rejected because it prevents us testing the specs on each
commit to Nova and means work that could be spread across multiple teams is
instead focused on one small team. It will result in more bugs and a lag
between changes to the Nova API and changes to the out-of-tree specs. It will
result in duplication of effort across Nova, Tempest, and the specs projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish the spec via an API resource rather than in our docs&lt;/p&gt;
&lt;p&gt;We could publish the spec via a new, unversioned API endpoint such as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/spec&lt;/span&gt;&lt;/code&gt;. A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; request to this would return the full spec, either
statically generated at deployment time or dynamically generated (and then
cached) at runtime.&lt;/p&gt;
&lt;p&gt;This is rejected because it brings limited advantages and multiple
disadvantages. Nova’s API is designed to be backwards-compatible and
non-extensible. As such, a user with the latest version of the spec should be
able to use it to communicate with any OpenStack deployment running a version
of Nova that supports microversions. It is also expected that the “master”
version of the spec will continuously improve as things are tightened up,
documentation is improved, and bugs or mistakes are corrected. We want
consumers of the spec to see these changes immediately rather than wait for
their deployment to be updated. Finally, OpenStack’s previous forays into
discoverable APIs, such as Keystone’s use of JSONHome or Glance’s attempts to
publish resource schemas, have seen limited take-up outside of the projects
themselves. Taken together, this all suggests there is no reason or advantage
to publishing deployment-specific specs and users would be better served by
fetching the latest version of the spec from the api-ref documentation
published on docs.openstack.org (which, one should note, is itself
intentionally unversioned).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no direct REST API impact. Users will see HTTP 500 error if they
set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;response_validation&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; and encounter an invalid response,
however, we will not encourage use of this option in production and will
instead focus on validating this ourselves in CI.&lt;/p&gt;
&lt;p&gt;We may wish to address issues that are uncovered as we add schemas, but this
work is considered secondary to this effort and can be tackled separately.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This should be very beneficial for users who are interested in developing
client and bindings for OpenStack. In particular, this should (after an initial
effort in code generation) reduce the workload of the SDK team as well as teams
outside of OpenStack that work on client tooling such as the Gophercloud team.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be a minimal impact on API performance when validation is enabled as
we will now verify both requests and responses for all API resources. Given our
existing extensive use of JSON Schema for API validation, it is expected that
this should not be a significant issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As noted previously, there will be one new config option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt;. Operators may see increased warnings in their logs due
to incomplete schemas, but most if not all of these issues should be ironed out
by our CI coverage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers working on the API microversions will now be encouraged to provide
JSON Schema schemas for both requests and responses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gtema&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add missing request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of request body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add missing query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of query string schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add decorator to validate response body schemas against response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests to validate existence of response body schemas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The actual generation of an OpenAPI documentation will be achieved via a
separate tool. It is not yet determined if this tool will live inside an
existing project, such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstacksdk&lt;/span&gt;&lt;/code&gt;, or inside a
wholly new project. In any case, it is envisaged that this tool will handle
OpenStack-specific nuances like microversions that don’t map 1:1 to OpenAPI
concepts in a consistent and documented fashion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests will ensure that schemas eventually exist for request bodies, query
strings, and response bodies.&lt;/p&gt;
&lt;p&gt;Unit, functional and integration tests will all work together to ensure that
response body schemas match real responses by setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt;
&lt;span class="pre"&gt;response_validation&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Initially there should be no impact as we will continue to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_api_ref&lt;/span&gt;&lt;/code&gt;
as-is for our &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;api-ref&lt;/span&gt;&lt;/code&gt; docs. Eventually we will replace or extend this
extension to generate documentation from our OpenAPI schema.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;section id="apis-missing-schemas"&gt;
&lt;h3&gt;APIs missing schemas&lt;/h3&gt;
&lt;p&gt;These are the APIs that are currently (as of 2024-04-11, commit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;1bca24aeb&lt;/span&gt;&lt;/code&gt;)
missing API request body schemas and query string schemas.&lt;/p&gt;
&lt;p class="rubric"&gt;Missing request body schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._inject_network_info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AdminActionsController._reset_network&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._add_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController._remove_interface&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.sync_instances&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._force_delete&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeferredDeleteController._restore&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.reserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.unreserve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LockServerController._unlock&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._associate_host&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_host_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkAssociateActionController._disassociate_project_only&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController._disassociate_host_and_project&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.add&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._pause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PauseServerController._unpause&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RemoteConsolesController.get_rdp_console&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RescueController._unrescue&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._addSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupActionController._removeSecurityGroup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.update&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupRulesController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_confirm_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._action_revert_resize&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._start_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController._stop_server&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShelveController._shelve_offload&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._resume&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SuspendServerController._suspend&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.create&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Missing request query string schemas&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AgentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AvailabilityZoneController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BareMetalNodeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.capacities&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CellsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CertificatesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CloudpipeController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsoleAuthTokensController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsolesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ExtensionInfoController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FixedIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorAccessController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorExtraSpecsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FlavorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPBulkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSDomainController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPDNSEntryController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FloatingIPPoolsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;FpingController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.reboot&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.shutdown&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostController.startup&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.search&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.statistics&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HypervisorsController.uptime&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IPsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceUsageAuditLogController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InterfaceAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaClassSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.defaults&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QuotaSetsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SecurityGroupDefaultRulesController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerDiagnosticsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerGroupController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMetadataController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerMigrationsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerPasswordController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerSecurityGroupController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTagsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerTopologyController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServerVirtualInterfaceController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ServersController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SnapshotController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.index&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TenantNetworkController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VersionsController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeAttachmentController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VolumeController.show&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We should emphasise that many - but not all - of the aforementioned APIs
are either deprecated or removed. We may wish &lt;em&gt;not&lt;/em&gt; to add schemas for
these, though by doing so we will lose the ability to generate documentation
or clients for these APIs from the OpenAPI spec.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 09 Sep 2024 00:00:00 </pubDate></item><item><title>libvirt driver launching instances with memory encryption by AMD SEV-ES</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/amd-sev-es-libvirt-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/amd-sev-es-libvirt-support"&gt;https://blueprints.launchpad.net/nova/+spec/amd-sev-es-libvirt-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes work required in order to extend the existing libvirt driver
feature to launch AMD SEV-encrypted instances, to support also using AMD
SEV-ES, which is the extended version of AMD SEV, as memory encryption
mechanism.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current libvirt driver supports launching instances with memory encryption by
&lt;a class="reference external" href="https://developer.amd.com/sev/"&gt;AMD’s SEV (Secure Encrypted Virtualization) technology&lt;/a&gt;. However the current implementation supports
only AMD SEV, and does not support new versions. For exmaple SEV-ES also
encrypts all CPU register contents when a VM stops running, to achieve more
complete protection of VM data, but users can’t leverage these features because
of this limitation.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;At the time or writing AMD already released CPUs which supports SEV-SNP, but
the required hypervisor features to use SEV-SNP are not yet merged into
the underlying components(kernel, QEMU, libvirt and ovmf). So in this spec
we focus on SEV-ES. We attempt to keep the proposal as much compatible with
SEV-SNP as possible, based on the implementations published by AMD.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud administrator, in order that my users can have more confidence
in the security of their running instances, I want to provide an image with
the specific properties or a flavor with the specific extra specs which will
allow users to boot instances to ensure that their instances run on
an SEV-ES-capable compute host with SEV-ES encryption, instead of SEV
encryption, enabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud user, in order to reduce data leakage risks further, I want to
be able to boot VM instances with SEV-ES functionality, instead of SEV
functionality, enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose extending the existing implementation to support launching instances
with SEV functionality.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV-ES capabilities, which checks the following items.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The presence of the following XML in the response from a libvirt
&lt;a class="reference external" href="https://libvirt.org/html/libvirt-libvirt-domain.html#virConnectGetDomainCapabilities"&gt;virConnectGetDomainCapabilities()&lt;/a&gt;
API call &lt;a class="reference external" href="https://libvirt.org/git/?p=libvirt.git;a=commit;h=6688393c6b222b5d7cba238f21d55134611ede9c"&gt;indicates that both QEMU and the AMD Secure Processor
(AMD-SP) support SEV functionality&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt; &lt;span class="n"&gt;supported&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Also the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxESGuests&lt;/span&gt;&lt;/code&gt; field should be present and its value should be
a positive (non-zero) value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/sys/module/kvm_amd/parameters/sev_es&lt;/span&gt;&lt;/code&gt; should have the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Y&lt;/span&gt;&lt;/code&gt;
to indicate that the kernel has SEV capabilities enabled.  This
should be readable by any user (i.e. even non-root).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check QEMU version to determine whether the available QEMU binary supports
SEV-ES.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait to os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the libvirt driver &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update the ProviderTree object&lt;/a&gt;
with the correct inventory for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource class
for both SEV and SEV-ES. To represent the slots dedicated for SEV and SEV-ES,
nested resource providers are created per-model:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+------------+&lt;/span&gt;     &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt; &lt;span class="o"&gt;+--+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ES&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The SEV RP is named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;nodename&amp;gt;_amd_sev&lt;/span&gt;&lt;/code&gt; and the SEV-ES RP is named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;nodename&amp;gt;_amd_sev_es&lt;/span&gt;&lt;/code&gt;, so that the RP names are unique in the cluster.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV and SEV-ES have separate limits of guest numbers, because ASIDs are
allocated for ES guests and non-ES guests exclusively, from the total
ASIDs available. Minimum ASID for SEV (non-ES) guests, which is
effectively same as maxumum ASID for ES guests, should be configured in
BIOS (or UEFI) to use SEV-ES. A new validation to detect insufficient
ASIDs may be implemented.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV-SNP uses the same ASID pool for ES by default when cyphertext hiding
is not requested, and the new trait (such as HW_CPU_AMD_SEV_SNP) may be
added to the existing SEV-ES RP when SEV-SNP support is added with
a separate SEV-SNP RP with the trait corrsponding to the cyphertext hiding
feature:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+------------+&lt;/span&gt;     &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt; &lt;span class="o"&gt;+--+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ES&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_SNP&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------------+---+&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+-----------------------------+&lt;/span&gt;
                &lt;span class="o"&gt;+--+&lt;/span&gt; &lt;span class="n"&gt;SEV&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SNP&lt;/span&gt; &lt;span class="n"&gt;RP&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_AMD_SEV_SNP_CH&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+----+&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
                   &lt;span class="o"&gt;+------------------------+----+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that SEV-SNP support is out of the current scope and this design
needs further dicsussion when the support is actually implemented. It is
described here to explain the potential plan to extend the RP structure
in the future.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model&lt;/span&gt;&lt;/code&gt; parameter in flavor
extra specs, and a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model&lt;/span&gt;&lt;/code&gt; image property. When
either of these is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt; along with the parameter/propery to
enable memory encryption, it would be internally translated to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV_ES=required&lt;/span&gt;&lt;/code&gt; which would be added to the flavor extra
specs in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; object. If these new model parameter/property is
absent or set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev&lt;/span&gt;&lt;/code&gt; then it would be translated to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV=required&lt;/span&gt;&lt;/code&gt;. If conflicting models are requested by
the instance flavor and the instance image (for example the flavor has
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model=amd-sev&lt;/span&gt;&lt;/code&gt; but the image has
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model=amd-sev-es&lt;/span&gt;&lt;/code&gt;) then the request is rejected. Also
the request should be rejected when memory encryption is not requested but
a memory encryption model is requested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the libvirt driver to include extra XML in the guest’s domain
definition when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption_model&lt;/span&gt;&lt;/code&gt; parameter in flavor extra
spec or the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption_model&lt;/span&gt;&lt;/code&gt; image property is present and
is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt;. The extra XML is mostly similar to the one used in
SEV, but its guest policy field needs the SEV-ES bit (bit 2) enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Guest attestation is currently out of our scope. Because &lt;a class="reference external" href="https://libvirt.org/kbase/launch_security_sev.html#guest-attestation-for-sev-sev-es-from-a-trusted-host"&gt;the existing
feature for guest attestation&lt;/a&gt;
heavily depends on hypervisor features and is not suitable for confidential
computing use case where users do not trust hypervisors. We aim to implement
the guest attestation feature once SEV-SNP is generally available, because
SEV-SNP provides a better mechanism for guest attestation, using the special
device presented to guest machines to obtain attestation reports.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The end user will harness SEV-ES through the existing mechanisms of resources
in flavor extra specs and image properties.&lt;/p&gt;
&lt;p&gt;Also &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html#impermanent-limitations"&gt;the limitations of AMD SEV-encrypted guest&lt;/a&gt;
are applied when SEV-ES is used.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No performance impact on nova is anticipated.&lt;/p&gt;
&lt;p&gt;Performance impact for the other parts are same as the existing SEV support
feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In order for users to be able to use SEV-ES, the operator will need to
perform the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy SEV-ES-capable hardware as nova compute hosts.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;AMD EPYC 7xx2 (Rome) or later&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set minimum ASID for SEV (non-ES) guests in BIOS (or UEFI) to a value greater
than 0.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If SEV-enabled instancs are already launched in the compute node, enough
ASIDs should be reserved for SEV.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that they have an appropriately configured software stack, so
that the various layers are all SEV-ES ready:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;kernel &amp;gt;= 4.16&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;= 6.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libvirt &amp;gt;= 8.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ovmf &amp;gt;= commit 7f0b28415cb4 2020-08-12&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;SEV-ES enabled guests can be launched by libvirt &amp;gt;= 4.5, but detection of
maximum number of SEV-ES guests via domain capability API requires libvirt
&amp;gt;= 8.0.0 .&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A cloud administrator will need to define SEV-ES-enabled flavors as described
above, unless it is sufficient for users to define SEV-ES-enabled images.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;[libvirt] num_memory_encrypted_guests&lt;/cite&gt; option is effective only for SEV,
but a new option for SEV-ES is NOT added. Instead, the detection capability in
libvirt is required to use SEV-ES. The &lt;cite&gt;num_memory_encrypted_guests&lt;/cite&gt; option
will be deprecated to reduce complexity.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kajinamit (irc: tkajinam)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait for os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV-ES capabilities as detailed above and reshaping
of existing MEMO_ENCRYPTION_CONTEXT resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property to ImageMeta object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update scheduler util to request &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV_ES&lt;/span&gt;&lt;/code&gt; trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property or
the equivalent flavor extra spec is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;amd-sev-es&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update libvirt driver to set the SEV-ES policy bit when the property is
present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update image property schema in glance to validate the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mem_encryption_model&lt;/span&gt;&lt;/code&gt; property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unit tests and functional tests should be added according to new logic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="future-work"&gt;
&lt;h3&gt;Future work&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Special hardware which supports SEV-ES for development, testing, and CI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recent versions of the hypervisor software stack which all support
SEV-ES, as detailed in &lt;a class="reference internal" href="#other-deployer-impact"&gt;Other deployer impact&lt;/a&gt; above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fakelibvirt&lt;/span&gt;&lt;/code&gt; test driver will need adaptation to emulate
SEV-ES-capable hardware.&lt;/p&gt;
&lt;p&gt;Corresponding unit/functional tests will need to be extended or added
to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;detection of SEV-ES-capable hardware and software, e.g. perhaps as an
extension of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.functional.libvirt.test_report_cpu_traits.LibvirtReportTraitsTests&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the use of a trait to include extra SEV-specific libvirt domain XML
configuration, e.g. within
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.unit.virt.libvirt.test_config&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the entry in &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/support-matrix.html"&gt;the Feature Support Matrix&lt;/a&gt;,
to explain now AMD SEV-ES is supported in addition to AMD SEV.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the existing &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/sev.html"&gt;AMD SEV&lt;/a&gt; guide to include
information about SEV-ES.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other non-nova documentation should be updated too:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/os-traits/latest/"&gt;documentation for os-traits&lt;/a&gt; should be extended
where appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/sev"&gt;AMD SEV landing page&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/55766.PDF"&gt;AMD SEV-KM API Specification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/AMDESE/AMDSEV/"&gt;AMD SEV github repository containing examples and tools&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://events17.linuxfoundation.org/sites/events/files/slides/AMD%20SEV-ES.pdf"&gt;Slides from the 2017 Linux Security Summit describing SEV and
preliminary performance results&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#sev"&gt;libvirt’s SEV options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sun, 21 Jul 2024 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2025.1/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2025.1 Epoxy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 16 Jul 2024 00:00:00 </pubDate></item><item><title>Config option to control behavior of unset unified limits</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/unified-limits-nova-unset-limits.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unified-limits-nova-unset-limits"&gt;https://blueprints.launchpad.net/nova/+spec/unified-limits-nova-unset-limits&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The default behavior in the oslo.limit quota enforcement library used by Nova
when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; is to
consider resources that do not have registered limits set as having a limit of
zero. This behavior can be unforgiving especially in the scenario of an
upgrade that enables unified limits quota (i.e. if we ever want to make unified
limits the default). If we make the behavior configurable within Nova, we can
help prevent situations where an admin/operator upgrades or installs Nova and
suddenly all API requests begin to be rejected for being over quota.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The problem is centered around the behavior of the oslo.limit quota enforcement
library when a given resource does not have a registered limit set for it. If
no registered limit is found for a resource, the enforce function will consider
that resource to have a limit of 0 and all requests for the resource will fail
for being over quota.&lt;/p&gt;
&lt;p&gt;We want to be able to change the default quota driver to the
UnifiedLimitsDriver, but the aforementioned behavior raises concerns about
changing the default.&lt;/p&gt;
&lt;p&gt;If we were to make unified limits quotas the default in Nova, any
admin/operator who has missed auditing all of their resources and limits in
Keystone before upgrading could experience complete denial of service by the
Nova API immediately after the upgrade. This could happen if even one resource
is missing a registered limit set in Keystone.&lt;/p&gt;
&lt;p&gt;While ideally an admin/operator will not miss setting any registered limits in
an upgrade scenario like this, the penalty for missing even one resource limit
is quite harsh as the API rejects all requests for that resource leading to an
immediate emergency situation.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator, I would like to be warned if I have missed setting a
registered limit for a resource in Keystone rather than having all API
requests involving that resource be rejected for being over quota&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposal in this spec is to add a new configuration option
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; which defaults to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;. When set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, the Nova API will use the native oslo.limit behavior of considering
unset unified limits as zero. When set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;, the Nova API will consider
unset unified limits as unlimited or “don’t care”. When set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, the
Nova API will use the native oslo.limit behavior of considering unset unified
limits as zero.&lt;/p&gt;
&lt;p&gt;The only exception to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; is if there are
not registered limits set at all. &lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/admin/unified-limits.html#registered-limits"&gt;Registered limits&lt;/a&gt; are default limits that
are global to the deployment and apply in any case that a project-specific
limit has not been set. If unified limits are enabled but no registered limits
have been set, all quota checks will fail and log a warning message about the
total absence of any limits set every time quota is enforced. The combination
of unified limits enabled but no unified limits set is considered to be an
error state and not something the admin/operator has intended. We could also
consider failing to start the nova-api and nova-conductor services if unified
limits are enabled but no limits are set.&lt;/p&gt;
&lt;p&gt;The idea of the proposed config option is to give the admin/operator some
flexibility to resolve a situation where not all resources have registered
limits set without immediately rejecting API requests. Of course, there will be
the risk of potentially allowing allocation of more resources than would be
desired until the admin/operator either sets registered limits or disables
unified limits quotas. A warning will be logged every time quota is enforced
for resources without registered limits set because we don’t want or expect
unset limits to be a permanent state. The admin/operator can stop the warning
logs by setting registered limits for the resources listed in the warning
message.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Alternatively a change could be made to the oslo.limit library to handle
missing registered limits differently &lt;a class="reference external" href="https://review.opendev.org/c/openstack/oslo.limit/+/899415"&gt;[1]&lt;/a&gt;. This would be more difficult
because oslo.limit has established default behavior and providing new behavior
desirable for all projects may not be realistic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;, resources could be
allocated beyond what the admin/operator would have intended during the window
of time between the logging of the warning and the admin/operator taking action
to either set registered limit(s) or disable unified limits quotas.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;As part of this work, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt; &lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt; CLI
command will be enhanced to scan the database for resources in flavors that do
not have registered limits set and show them in the output. The intent is to
help admins/operators catch all resources and set limits for them before
unified limits quotas are enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The performance impact of having &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; should be relatively small as it adds one extra Keystone API call
each time a quota check fails and the limit for the associated resource is 0.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Admin/operators will need to be prepared and set
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; _before_ upgrading Nova if they
wish to relax quota checks initially when enabling unified limits quotas.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; config option would only impact an upgrade
if the admin/operator sets it to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; at the same time they enable unified
limits quotas by using the UnifiedLimitsDriver.&lt;/p&gt;
&lt;p&gt;If a deployer decides to switch to the UnifiedLimitsDriver during their upgrade
and set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; before upgrading, there
is a possibility that resources could be allocated beyond what the deployer
would have intended until they take action on the logged warnings and set
registered limits for resources missing limits.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a configuration option to control whether unset unified limits should be
considered unlimited and logged as a warning&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Augment the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt; &lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt; command to scan
database flavors to detect resources that do not have registered limits set
and show them in the output to the user to let them know which limits they
need to set&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Related to &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The functionality of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]strict_unified_limits&lt;/span&gt;&lt;/code&gt; config option will be
tested by writing new functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/unified-limits.html"&gt;unified limits documentation&lt;/a&gt; will be updated to include information
about the new config option.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/unified-limits.html"&gt;https://docs.openstack.org/nova/latest/admin/unified-limits.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.limit/latest/user/usage.html"&gt;https://docs.openstack.org/oslo.limit/latest/user/usage.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 10 Jul 2024 00:00:00 </pubDate></item><item><title>Per Process Healthcheck endpoints</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/per-process-healthchecks.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks"&gt;https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In many modern deployment frameworks, there is an expectation that
an application can expose a health-check endpoint so that the binary
status can be monitored. Nova currently does not provide a native way
to inspect the health of its binaries which doesn’t help cloud monitoring
and maintenance. While limited support exists for health checks via
Oslo middleware for our WSGI based API binaries, this blueprint seeks
to expose a local HTTP health-check endpoint to address this
feature gap consistently for all Nova components.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;To monitor the health of a Nova service today requires experience to
develop and implement a series of external heuristics to infer the state
of the service binaries.&lt;/p&gt;
&lt;p&gt;This can be as simple as checking the service status for those with heartbeats
or can comprise monitoring log output via a watchdog and restarting
the service if no output is detected after a protracted period.
Processing the logs for known error messages and executing a remediation script
or other methods that are easy to do incorrectly are also common.&lt;/p&gt;
&lt;p&gt;This is also quite unfriendly to new Nova users who have not gained enough
experience with operating Nova to know what warning signs they should look
for such as inability to connect to the message bus. Nova developers however
do know what some of the important health indicators are and can expose
those as a local health-check endpoint that operators can use instead.&lt;/p&gt;
&lt;p&gt;The existing Oslo middleware does not address this problem statement because:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;It can only be used by the API and metadata binaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The middleware does not tell you the service is alive if its hosted by a
WSGI server like Apache since the middleware is executed independently from
the WSGI application. i.e. the middleware can pass while the nova-api can’t
connect to the DB and is otherwise broken.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Oslo middleware in detailed mode leaks info about the host Python
kernel, Python version and hostname which can be used to determine in the
host is vulnerable to CVEs which means it should never be exposed to the
Internet. e.g.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Linux-5.15.2-xanmod1-tt-x86_64-with-glibc2.2.5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;python_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3.8.12 (default, Aug 30 2021, 16:42:10) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[GCC 10.3.0]'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want a simple REST endpoint I can consume to know
if a Nova process is healthy.&lt;/p&gt;
&lt;p&gt;As an operator I want this health check to not impact the performance of the
service so it can be queried frequently at short intervals.&lt;/p&gt;
&lt;p&gt;As a deployment tool implementer, I want the health check to be local with no
dependencies on other hosts or services to function so I can integrate it with
service managers such as systemd or a container runtime like Docker.&lt;/p&gt;
&lt;p&gt;As a packager, I would like the use of the health check endpoints to not
require special clients or packages to consume them. cURL, socat, or netcat
should be all that is required to connect to the health check and retrieve the
service status.&lt;/p&gt;
&lt;p&gt;As an operator I would like to be able to use health-check of the Nova API and
metadata services to manage the membership of endpoints in my load-balancer
or reverse proxy automatically.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="definitions"&gt;
&lt;h3&gt;Definitions&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TTL&lt;/span&gt;&lt;/code&gt;: The time interval for which a health check item is valid.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;: all health indicators are passing and their TTLs have not expired.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;: any health indicator has an expired TTL or where there is
a partial transient failure.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;: any health indicator is reporting an error or all TTLs are expired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="warn-vs-fail"&gt;
&lt;h3&gt;Warn vs fail&lt;/h3&gt;
&lt;p&gt;In general if any of the health check indicators are failing then the service
should be reported as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; however if the specific error condition is
recoverable or only a partial failure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state can and should be
used.&lt;/p&gt;
&lt;p&gt;An example of this is a service that has lost a connection to the message bus.
When the connection is lost it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state, if the first
attempt to reconnect fails it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state. Transient
failure should be considered warning but persistent errors should be escalated
to failures.&lt;/p&gt;
&lt;p&gt;In many cases external management systems will treat &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; as
equivalent and raise an alarm or restart the service. While this spec does
not specify how you should recover from a degraded state, it is
important to include a human readable description of why the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state was entered.&lt;/p&gt;
&lt;p&gt;Services in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state are still considered healthy in most cases but
they may be about to fail soon or be partially degraded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;Code changes&lt;/h3&gt;
&lt;p&gt;A new top-level Nova health check module will be created to encapsulate the
common code and data structure required to implement this feature.&lt;/p&gt;
&lt;p&gt;A new health check manager class will be introduced which will maintain the
health-check state and all functions related to retrieving, updating and
summarizing that state.&lt;/p&gt;
&lt;p&gt;The health check manager will be responsible for creating the health check
endpoint when it is enabled in the nova.conf and exposing the health check
over HTTP.&lt;/p&gt;
&lt;p&gt;The initial implementation will support HTTP over TCP with optional support for
UNIX domain sockets as a more secure alternative to be added later.
The HTTP endpoint in both cases will be unauthenticated and the response will
be in JSON format.&lt;/p&gt;
&lt;p&gt;A new HealthcheckStausItem data class will be introduced to store an
individual health check data-point. The HealtcheckStatusItem will contain
the name of the health check, its status, the time it was recorded,
and an optional output string that should be populated if the
status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A new decorator will be introduced that will automatically retrieve the
reference to the healthcheck manager from the Nova context object and update
the result based on whether the function decorated raises an exception or not.
The exception list and healthcheck item name will be specifiable.&lt;/p&gt;
&lt;p&gt;The decorator will accept the name of the health check as a positional argument
and include the exception message as the output of the health check on failure.
Note that the decorator will only support the pass or fail status for
simplicity; where warn is appropriate a manual check should be written.
If multiple functions act as indicators of the same capability the same name
should be used.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_other_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default all exceptions will be caught and re-raised by the decorator.&lt;/p&gt;
&lt;p&gt;The new REST health check endpoint exposed by this spec will initially only
support one URL path &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt;. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; endpoint will include a
&lt;cite&gt;Cache-Control: max-age=&amp;lt;ttl&amp;gt;&lt;/cite&gt; header as part of its response which can
optionally be consumed by the client.&lt;/p&gt;
&lt;p&gt;The endpoint may also implement a simple incrementing etag at a later date
once the initial implementation is complete, if required.
Initially adding an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; is not provided as the response is expected to be
small and cheap to query, so etags do not actually provide much benefit form
a performance perspective.&lt;/p&gt;
&lt;p&gt;If implemented, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; will be incremented whenever the service state
changes and will reset to 0 when the service is restarted.&lt;/p&gt;
&lt;p&gt;Additional URL paths may be supported in the future, for example to retrieve
the running configuration or trigger the generation of Guru Meditation Reports
or enable debug logging. However, any endpoint beyond &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; is out of
scope of this spec. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; is not used for health check response to facilitate
additional paths in the future.&lt;/p&gt;
&lt;section id="example-output"&gt;
&lt;h4&gt;Example output&lt;/h4&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"e3c22423-cd7a-47dc-b6e9-e18d1a8b3bdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"api_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="n"&gt;Sevice&lt;/span&gt; &lt;span class="n"&gt;Unavailable&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0a47dceb-11b1-4d94-8b9c-927d998be320"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-compute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"hypervisor"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
             &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:05:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s2"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Libvirt Error: ..."&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of maintaining the state of the process in a data structure and
returning the cached state we, could implement the health check as a series of
active probes such as checking the DB schema version to ensure we can access
it or making a ping RPC call to the cell conductor or our own services RPC
endpoint.&lt;/p&gt;
&lt;p&gt;While this approach has some advantages it will have a negative performance
impact if the health-check is queried frequently or in a large deployment where
infrequent queries may still degrade the DB and message bus performance due to
the scale of the deployment.&lt;/p&gt;
&lt;p&gt;This spec initially suggested using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OK&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Degraded&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Faulty&lt;/span&gt;&lt;/code&gt; as the
values for the status field. These were updated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; to align with the draft IETF RFC for health check response format for
HTTP APIs &lt;a class="reference external" href="https://tools.ietf.org/id/draft-inadarei-api-health-check-06.html"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The Nova context object will be extended to store a reference to the
health check manager.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While this change will expose a new REST API endpoint it will not be
part of the existing Nova API.&lt;/p&gt;
&lt;p&gt;In the Nova API the /health check route will not initially be used to allow
those that already enable the Oslo middleware to continue to do so.
In a future release Nova reserves the right to add a /health check endpoint
that may or may not correspond to the response format defined in Oslo.
A translation between the Oslo response format and the health check module
may be provided in the future but it is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The new health check endpoint will be disabled by default.
When enabled it will not provide any authentication or explicit access control.
The documentation will detail that when enabled, the TCP endpoint should be
bound to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;localhost&lt;/span&gt;&lt;/code&gt; and that file system permission should be used to secure
the UNIX socket.&lt;/p&gt;
&lt;p&gt;The TCP configuration option will not prevent binding it to a routable IP if
the operator chooses to do so. The intent is that the data contained in the
endpoint will be non-privileged however it may contain hostnames/FQDNs or other
infrastructure information such as service UUIDs, so it should not be
accessible from the Internet.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While the health checks will use the ability to send notification as an input
to determine the health of the system, this spec will not introduce any new
notifications and as such it will not impact the Notification subsystem in
Nova. New notifications are not added as this would incur a performance
overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;At present, it is not planned to extend the Nova client or the unified client
to query the new endpoint. cURL, socat, or any other UNIX socket or TCP HTTP
client can be used to invoke the endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;We expect there to be little or no performance impact as we will be taking a
minimally invasive approach to add health indicators to key functions
which will be cached in memory. While this will slightly increase memory usage
there is no expected impact on system performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new config section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;healthcheck&lt;/span&gt;&lt;/code&gt; will be added in the nova.conf&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uri&lt;/span&gt;&lt;/code&gt; config option will be introduced to enable the health check
functionality. The config option will be a string opt that supports a
comma-separated list of URIs with the following format&lt;/p&gt;
&lt;p&gt;uri=&amp;lt;scheme&amp;gt;://[host:port|path],&amp;lt;scheme&amp;gt;://[host:port|path]&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The URI should be limited to the following characters &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[a-zA-Z0-9_-]&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;,&lt;/span&gt;&lt;/code&gt; is reserved as a separation character, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; may only be used in IPv4
addresses, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt; is reserved for port separation unless the address is an
IPv6 address. IPv6 addresses must be enclosed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[&lt;/span&gt;&lt;/code&gt; and  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;]&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; may
be used with the UNIX protocol however relative paths are not supported.
These constraints and the parsing of the URI will be enforced and provided by
the RFC3986 lib &lt;a class="reference external" href="https://pypi.org/project/rfc3986/"&gt;https://pypi.org/project/rfc3986/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt; IntOpt will be added with a default value of 300 seconds.
If set to 0, the time to live of a health check item will be infinite.
If the TTL expires, the state will be considered unknown and the healthcheck
item will be discarded.&lt;/p&gt;
&lt;p&gt;A cache_control IntOpt will be provided to set the max-age value in the
cache_control header. By default it will have the same max-age as the TTL
config option. Setting this to 0 will disable the reporting of the header.
Setting this to -1 will report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Cache-Control:&lt;/span&gt; &lt;span class="pre"&gt;no-cache&lt;/span&gt;&lt;/code&gt;.
Any other positive integer value will be used as the max-age.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers should be aware of the new decorator and consider whether it should
be added to more functions, if that function is an indicator of the system’s
health. Failures due to interactions with external systems such as Neutron port
binding external events should be handled with caution. While failure to
receive a port binding event will likely result in the failure to boot a VM, it
should not be used as a health indicator for the nova-compute agent. This is
because such a failure may be due to a failure in Neutron, not Nova. As such,
other operations such as VM snapshot may be unaffected and the Nova compute
service may be otherwise healthy. Any failure to connect to a non-OpenStack
service such as the message bus, hypervisor, or database should be treated as a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; health indicator if it prevents the Nova binary from
functioning correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce decorator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend context object to store a reference to health check manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose TCP endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose UNIX socket endpoint support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested entirely with unit and functional tests, however,
Devstack will be extended to expose the endpoint and use it to determine
whether the Nova services have started.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The config options will be documented in the config reference
and a release note will be added for the feature.&lt;/p&gt;
&lt;p&gt;A new health check section will be added to the admin docs describing
the current response format and how to enable the feature and its intended
usage. This document should be evolved whenever the format changes or
new functionality is added beyond the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Yoga PTG topic:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415"&gt;https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 10 May 2024 00:00:00 </pubDate></item><item><title>Use extend volume completion action</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/assisted-volume-extend.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend"&gt;https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume
action that has been proposed for Cinder in &lt;a class="footnote-reference brackets" href="#id12" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, to provide feedback on
success or failure when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server events.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many remotefs-based volume drivers in Cinder use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;resize&lt;/span&gt;&lt;/code&gt;
command to extend volume files.
However, when the volume is attached to a guest, QEMU will lock the file and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt;&lt;/code&gt; will be unable to resize it.&lt;/p&gt;
&lt;p&gt;In this case, only the QEMU process holding the lock can resize the volume,
which can be triggered through the QEMU monitor command &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is currently no adequate way for Cinder to use this feature, so the NFS,
NetApp NFS, Powerstore NFS, and Quobyte volume drivers all disable extending
attached volumes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I want to extend a NFS/NetApp NFS/Powerstore NFS/Quobyte volume
while it is attached to an instance and I want the volume size and status to
reflect the success or failure of the operation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova’s libvirt driver uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command when handling the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event, to inform QEMU that the size of an
attached volume has changed.
It is in principle also capable of extending a volume file, but is currently
unable to provide feedback to Cinder on the success of the operation.&lt;/p&gt;
&lt;p&gt;Currently, Cinder will send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event to
Nova only after it has finalized the extend operation and reset the volume
status from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;a class="footnote-reference brackets" href="#id12" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, Cinder will allow volume drivers to hold off finalizing the extend
operation and leave the volume status as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, until after it has
send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event and received feedback from Nova in form of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action, with an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; argument
indicating whether to finalize or to roll back the operation.&lt;/p&gt;
&lt;p&gt;This will currently affect only the volume drivers mentioned above, all of
which did not previously support online extend.
All other drivers will continue to send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event after
finalizing the operation and resetting to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt; status, and will not
expect a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action.&lt;/p&gt;
&lt;section id="compute-agent"&gt;
&lt;h3&gt;Compute Agent&lt;/h3&gt;
&lt;p&gt;Nova’s compute agent will use the volume status to differentiate between the
two behaviors when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the volume status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, then it will attempt to read
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; from the volume’s metadata and use this value as the
new size of the volume, instead of the volume size field.&lt;/p&gt;
&lt;p&gt;After successfully extending the volume, it will call the extend volume
completion action of the volume, with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;false&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If anything goes wrong, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; being missing from the
metadata, or being smaller than the current size of the volume, it will
log the error and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;, so Cinder can roll back the operation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For any other volume status, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, the event will be handled
as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="api"&gt;
&lt;h3&gt;API&lt;/h3&gt;
&lt;p&gt;Nova’s API will introduce a new microversion, so that Cinder can make sure the
new behavior is available, before leaving an extend operation unfinished.&lt;/p&gt;
&lt;p&gt;To handle older compute agents during a rolling upgrade, the API will also
check the compute service version of the target agent when receiving a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event with the new microversion.
If a target compute agent is too old to support the feature, the API will
discard the event and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A previous change tried to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event
to support online extend for the NFS driver &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but did not rely on
feedback from Nova to Cinder at all.
Instead, it would just set the new size of the volume, change the status
back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, notify Nova, and hope for the best.&lt;/p&gt;
&lt;p&gt;If anything went wrong on Nova’s side, this would still result in a volume
state indicating that the operation was successful, which is not acceptable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A previous version of this spec proposed a new synchronous API in Nova &lt;a class="footnote-reference brackets" href="#id11" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;,
that would directly call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CompVirtAPI.extend_image&lt;/span&gt;&lt;/code&gt; of the nova-compute
instance managing the guest that a volume was attached to.
This API would provide a single mechanism to trigger the resize operation,
communicate the new size to Nova, and get feedback on the success of the
operation.&lt;/p&gt;
&lt;p&gt;The problem with a synchronous API is, that RPC and API timeouts limit the
maximum time an extend operation can take.
For QEMU, this seemed to be acceptable, because storage preallocation is
hard disabled for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command, and because all currently
plausible file systems support sparse file operations.&lt;/p&gt;
&lt;p&gt;However, this may not be true for other volume or virt drivers that might
require this API in the future.
It would also break with the established pattern of asynchronous
coordination between Nova and Cinder, which includes the assisted snapshot
and volume migration features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Following this pattern, we could make the proposed API asynchronous and use
a new callback in Cinder, similar to Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-assisted-volume-snapshots&lt;/span&gt;&lt;/code&gt;
API, which uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-update_snapshot_status&lt;/span&gt;&lt;/code&gt; snapshot action to provide
feedback to Cinder.&lt;/p&gt;
&lt;p&gt;The function of the new Nova API would then just be to trigger the operation
and to communicate the new size.
The question is then, whether that warrants adding a new API to Nova, since
there are existing mechanisms that could be used for either.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The existing mechanism for triggering the extend operation in Nova is of
course the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event.
Using it for this purpose, as this spec proposes, requires the target size
to be transferred separately, because external server events only have a
single text field that is freely usable, which for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt;
is already used for the volume ID.&lt;/p&gt;
&lt;p&gt;Besides storing it in the admin metadata, as &lt;a class="footnote-reference brackets" href="#id12" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and this spec propose,
there is also the option of updating the size field of the volume, as &lt;a class="footnote-reference brackets" href="#id10" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
was essentially doing.&lt;/p&gt;
&lt;p&gt;This would require the volume size field to be reset on a failure.
If an error response from Nova was lost, the volume would just keep the new
size.
We would need to extend &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-reset_status&lt;/span&gt;&lt;/code&gt; to allow a size reset, or
something similar to clean up volumes like this.
This would be possible, but updating the size field only after the volume
was successfully extended seems like a cleaner solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could also extend the external server event API to accept additional data
for events, and use this to communicate the new size to Nova.&lt;/p&gt;
&lt;p&gt;This option was judged favorably by reviewers on the previous version of
this spec, &lt;a class="footnote-reference brackets" href="#id11" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but it would be a more complex change to the Nova API.&lt;/p&gt;
&lt;p&gt;However, if additional data fields become available in a future version of
the external server event API, it would be a relatively minor change to use
this instead of volume metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The behavior of the external server event API will change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If Nova receives a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event, and the referenced volume has
status of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, Nova will look for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; key in
the volume metadata, and use this instead of the volume size field as the
target size to update the block device mapping and to pass to the virt
driver’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_volume&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Nova will also attempt to call Cinder’s new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt;
volume action proposed in &lt;a class="footnote-reference brackets" href="#id12" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to let Cinder know if the operation was
successful or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, the API will behave as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Checking the target compute service version allows the API to handle rolling
upgrades gracefully.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kgube&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the external server event API to check the target compute service
version for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeVirtAPI.extend_volume&lt;/span&gt;&lt;/code&gt; method to follow the behavior
outlined in &lt;a class="reference internal" href="#compute-agent"&gt;Compute Agent&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt NFS job in the Nova gate to validate online extend.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The first two patches of &lt;a class="footnote-reference brackets" href="#id12" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; have been merged in 2024.1, so the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action is now available in microversion 3.71
of the Block Storage API and supported in the 9.5.0 release of
python-cinderclient.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We should test that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; gets called correctly
in all possible error or success condition if a volume has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;
status.&lt;/p&gt;
&lt;p&gt;We should test the case that the call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; fails.&lt;/p&gt;
&lt;p&gt;We also need to test that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; continues to be handled correctly
for volumes not in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; status.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new behavior of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event should be added to the
documentation of the external server event API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/739079"&gt;https://review.opendev.org/c/openstack/cinder/+/739079&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id4"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/855490/6"&gt;https://review.opendev.org/c/openstack/nova-specs/+/855490/6&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id9"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/cinder/+spec/extend-volume-completion-action"&gt;https://blueprints.launchpad.net/cinder/+spec/extend-volume-completion-action&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id13"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 26 Apr 2024 00:00:00 </pubDate></item><item><title>libvirt SPICE direct consoles</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/libvirt-spice-direct-consoles.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-spice-direct-consoles"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-spice-direct-consoles&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes modifications to Nova’s libvirt driver to support
“direct” SPICE VDI consoles. These consoles are “direct” in that they are not
intended to use a HTML5 transcoding proxy to access, and instead the user would
use a native SPICE client like &lt;cite&gt;remote-viewer&lt;/cite&gt;. Such a facility enables a much
richer virtual desktop experience that Nova current supports, in return for
relatively minor changes to Nova. A new Nova API microversion is also required
to allow users of these consoles to lookup connection details for the console.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The SPICE protocol was added to Nova a long time ago, and still represents the
richest and most performant option for remote desktops using Nova. However at
the moment, Novas’s HTML5 transcoding proxy is the only way to access these
SPICE consoles, and the HTML5 interface does not support many of the more novel
features of the SPICE protocol, nor does it support high resolution desktops
well.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;As a developer, I don’t want these changes to make the Nova codebase even more
complicated.&lt;/em&gt; The changes proposed are relatively contained – a single new API
microversion, some changes to the domain XML generation code which are
optional, and associated tests.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As a deployer, I want to be able to use OpenStack to provide rich virtual
desktops to my users.&lt;/em&gt; This change facilitates such functionality, but does
require additional deployment steps such as setup to TLS certificates for your
hypervisors and management of a SPICE native proxy. There is a sample
implementation using Kolla-Ansible available, but other deployment systems
would need to integrate this functionality for it to be generally available.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As a deployer who doesn’t want rich desktop consoles, I don’t want this
functionality to complicate my deployment.&lt;/em&gt; When disabled, the changes to
deployments are minor – for example the extra USB passthrough devices and
sound devices in the domain XML are all deployer configurable and can be
disabled.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As an end user, I would like access to a richer desktop experience than is
currently available.&lt;/em&gt; Once these changes are integrated and Kerbside deployed,
a further change to either Horizon or Skyline will be required to orchestrate
console access via Kerbside. It is expected the complete end to end
functionality will take several releases to land before a fully seamless
experience is available. Once fully implemented, Horizon and Skyline will be
capable of delivering a &lt;cite&gt;.vv&lt;/cite&gt; configuration file for a specific console to a
client, who will then have seamless access to their virtual desktop. However,
a user will be able to use the &lt;cite&gt;openstack console url show&lt;/cite&gt; command immediately
to create a console session outside of our web clients.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposed solution is relatively simple – add an API microversion which
makes it possible to create a “spice-direct” console, and to lookup connection
details for that console from the API. The new console type and microversion is
required because we need to be able to specify the new console type, which is
an API schema change.&lt;/p&gt;
&lt;p&gt;The response from a &lt;cite&gt;get_spice_console&lt;/cite&gt; or &lt;cite&gt;create&lt;/cite&gt; call which requests a
“spice-direct” console will return a URL derived from
&lt;cite&gt;CONF.spice.kerbside_base_url&lt;/cite&gt;, and will include a console access token. The
user would then request this URL, and Kerbside would lookup console connection
details from nova via the &lt;cite&gt;/os-console-auth-tokens/&lt;/cite&gt; API. These details would
be used to generate a virt-viewer still .vv configuration file, which the user
can then use to access a proxied SPICE console.&lt;/p&gt;
&lt;p&gt;Because the response from &lt;cite&gt;/os-console-auth-tokens/&lt;/cite&gt; includes the host and port
on the hypervisor that the SPICE console is running on, it is agreed that these
API methods should have restricted accessibility. However, this is a
pre-existing API and this should already be true. This protects sensitive
network configuration information from being provided to less trusted users.&lt;/p&gt;
&lt;p&gt;This specification also covers tweaks the to the libvirt domain XML to enrich
the desktop experience provided by such a direct console, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;requiring an encrypted connection (WIP implementation at
Ica7083b0836f8d66cad8a4b4097613103fc91560)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;allowing concurrent users as supported by SPICE (WIP implementation at
I65f94771abdc1a6ef54637ea81f25ce1daaf4963)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;USB device passthrough from client to guest (WIP implementation at
I0cbd28be272991f95c8fb9d76ee65b2b99a8bcf1)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sound support (WIP implementation at
I4c98a0d6307c5e331df5caea80cb760512370058)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The proposed changes allow direct connection to a SPICE console from a SPICE
native client like &lt;cite&gt;remote-viewer&lt;/cite&gt;. Without additional software, this implies
that such a client would have network connectivity to relatively arbitrary TCP
ports on the hypervisor hosting the instance. However, a SPICE protocol native
proxy now exists, and a parallel proposal to this one proposes adding support
for it to Kolla-Ansible. This proxy is called Kerbside, and more details are
available at &lt;a class="reference external" href="https://github.com/shakenfist/kerbside"&gt;https://github.com/shakenfist/kerbside&lt;/a&gt;. That is, with the proxy
deployed there is effectively no change to the network exposure of Nova
hypervisors.&lt;/p&gt;
&lt;p&gt;As part of prototyping this functionality, a series of patches to Nova were
developed. These are available at
&lt;a class="reference external" href="https://github.com/shakenfist/kerbside-patches/tree/develop/nova"&gt;https://github.com/shakenfist/kerbside-patches/tree/develop/nova&lt;/a&gt; as well as
on gerrit at
&lt;a class="reference external" href="https://review.opendev.org/q/topic:%22kerbside-spice-direct-consoles%22"&gt;https://review.opendev.org/q/topic:%22kerbside-spice-direct-consoles%22&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;They are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Allow Nova to require secured SPICE connections, via a new &lt;cite&gt;require_secure&lt;/cite&gt;
configuration option in the SPICE configuration group.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an API microversion to expose the “spice-direct” console type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allowing concurrent connections to SPICE consoles for people who want to
share a console session.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supporting USB passthrough.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optionally enabling SPICE debugging in qemu.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding a sound device so that the consoles can do audio. This will be done
via a&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an optional dependency in Nova to the Kerbside API client library so that
Nova can fetch console connection details to proxy to a requesting user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When implemented, a user can fetch a Kerbside connection URL like this:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;`&lt;/span&gt;
&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;console&lt;/span&gt; &lt;span class="pre"&gt;url&lt;/span&gt; &lt;span class="pre"&gt;show&lt;/span&gt; &lt;span class="pre"&gt;--spice-direct&lt;/span&gt; &lt;span class="pre"&gt;52b2e44e-e561-464c-88f3-2fc6a1ecea2b&lt;/span&gt;
&lt;span class="pre"&gt;+----------+------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;Field&lt;/span&gt;    &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;Value&lt;/span&gt;                                                            &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;+----------+------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;protocol&lt;/span&gt; &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;spice&lt;/span&gt;                                                            &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;type&lt;/span&gt;     &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;spice-direct&lt;/span&gt;                                                     &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;url&lt;/span&gt;      &lt;span class="pre"&gt;|&lt;/span&gt; &lt;span class="pre"&gt;http://127.0.0.1:13002/nova?token=bf2e6883-...&lt;/span&gt;                   &lt;span class="pre"&gt;|&lt;/span&gt;
&lt;span class="pre"&gt;+----------+------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="pre"&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The user then fetches that URL, and Kerbside delivers a .vv file with the
connection information for a SPICE client. Kerbside uses a call to
&lt;cite&gt;/os-console-auth-tokens/bf2e6883-…&lt;/cite&gt; to determine the validity of the
console authentication token, and the connection information for the console.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Unfortunately the SPICE HTML5 proxy does not meet the needs to many remote
desktop users. Realistically OpenStack does not currently have a way of
providing these rich desktop consoles to users. Instead, other systems such as
Citrix are used for this functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The console auth token table needs to have an extra column added so that TLS
ports can be tracked alongside unencrypted ports. This change is minor and
should not be difficult for deployers to support as this table should not be
particularly large given authentication tokens already expire.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This specification adds a new console type, “spice-direct”, which provides
the connection information required to talk the native SPICE protocol
directly to qemu on the hypervisor. This is intended to be fronted
by a proxy which will handle authentication separately.&lt;/p&gt;
&lt;p&gt;A new microversion is introduced which adds the type “spice-direct”
to the existing “spice” protocol.&lt;/p&gt;
&lt;p&gt;This implies that the JSON schema for &lt;cite&gt;create&lt;/cite&gt; console call would change to
something like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;create_v297&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'remote_console'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'protocol'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'vnc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rdp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'serial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mks'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'novnc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'xvpvnc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spice-html5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="s1"&gt;'spice-direct'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'serial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'webmks'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'protocol'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'remote_console'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And that the JSON schema for the &lt;cite&gt;get_spice_console&lt;/cite&gt; would change to
something like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;get_spice_console_v297&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'os-getSPICEConsole'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'spice-html5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spice-direct'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'os-getSPICEConsole'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response from &lt;cite&gt;/os-console-auth-tokens/&lt;/cite&gt; also needs to be tweaked to return
a TLS port if one is configured for the console, which will require a response
schema change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This proposal has a medium security impact. While hypervisor host / port
details will only be exposed to requestors that have the &lt;cite&gt;service&lt;/cite&gt; role or
&lt;cite&gt;admin&lt;/cite&gt; permissions, Kerbside does need to have network connectivity to the
SPICE TCP ports on the hypervisors in the cloud. However, Kerbside provides a
protective layer to these TCP ports, and it is not intended to expose this
information to less privileged requestors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As discussed, a complete implementation requires deployment systems to
integrate the Kerbside SPICE proxy, as well as modifications to front ends
such as Horizon and Skyline to orchestrate consoles via Kerbside. However,
those are outside the scope of a Nova specification.&lt;/p&gt;
&lt;p&gt;The following configuration options are added by the proposed changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;spice.kerbside_base_url&lt;/cite&gt;: defaults to an example URL which wouldn’t actually
work for a non-trivial installation (just as the HTML5 transcoding proxy
does). This is the base URL for the Kerbside URLs handed out by Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;spice.require_secure&lt;/cite&gt;: defaults to &lt;cite&gt;False&lt;/cite&gt;, the current hard coded
default. Whether to require secure TLS connections to SPICE consoles. If
you’re providing direct access to SPICE consoles instead of using the
HTML5 proxy, you may wish those connections to be encrypted. If so, set
this value to True. Note that use of secure consoles requires that you
setup TLS certificates on each hypervisor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;spice.allow_concurrent&lt;/cite&gt;: defaults to &lt;cite&gt;False&lt;/cite&gt;, the current hard coded
default. Whether to allow concurrent access to SPICE consoles. SPICE
supports multiple users accessing the same console simultaneously, with
some reduced functionality for the second and subsequent users. Set this
option to True to enable concurrent access to SPICE consoles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;spice.debug_logging&lt;/cite&gt;: defaults to &lt;cite&gt;False&lt;/cite&gt;, the current hard coded
default. Whether to emit SPICE debug logs or not to the qemu log. These
debug logs are verbose, but can help diagnose some connectivity issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following additional image property will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;hw_audio_model&lt;/cite&gt;: defaults to &lt;cite&gt;None&lt;/cite&gt;, the current hard coded
default. Whether to include a sound device for instance when SPICE
consoles are enabled, and if so what type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, if SPICE consoles are enabled, then USB passthrough devices are
created in the guest. These devices are harmless if not used by a client
capable of using USB passthrough.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mikal&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Liaison needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Land the patches at
&lt;a class="reference external" href="https://github.com/shakenfist/kerbside-patches/tree/develop/nova"&gt;https://github.com/shakenfist/kerbside-patches/tree/develop/nova&lt;/a&gt;
in the order specified there, with any modifications requested by the Nova team
during code review.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Testing graphical user interfaces in the gate is hard. However, a test for the
API microversion will be added, and manual testing of the console functionality
has occurred on the prototype and will be redone as the patches land.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The Operators Guide will need to be updated to cover the new functionality and
configuration options. The End User’s guide will need to be updated to
explain usage once the functionality is fully integrated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sat, 06 Apr 2024 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result operators need to ensure that Manila
backend storage is routable from the guest subnets.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not
be covered by this spec, any requests to shelve, evacuate, resize, suspend,
cold migrate or live migrate an instance with a share attached will be
rejected with a HTTP409 response for the time being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
as it is now &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;supported by libvirt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.
(ref: &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user documentation&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Two new compute capability traits and filters will be introduced to model an
individual compute’s support for virtio-fs and file backed memory.
And while associating a share to an instance, a check will ensure the host
running the instance will support the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and either the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;that the instance is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;From an operator’s point of view, it means
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; support requires that
operators must upgrade all their compute nodes to the version supporting
shares using virtiofs.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; support requires that operators configure one or
more hosts with file backed memory. Ensuring the instance will land on one of
these hosts can be achieved by creating an AZ englobing these hosts.
And then instruct users to deploy their instances in this AZ.
Alternatively, operators can guide the scheduler to choose a suitable host
by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_MEM_BACKING_FILE=required&lt;/span&gt;&lt;/code&gt; as an extra spec or
image property.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the users with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;p&gt;Share mapping status:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                     &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;   &lt;span class="n"&gt;Reboot&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
    &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;--------------+&lt;/span&gt;
    &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;mounted&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;active&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;umount&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;error&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+-------------+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;detaching&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;φ&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Attach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;unmounted&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="n"&gt;v&lt;/span&gt;                                 &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+--------------&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="n"&gt;attaching&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inactive&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;φ&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means no entry in the database. No association between a share and a server.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Attach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means POST /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Detach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means DELETE /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This chart describe the share mapping status (nova), this is independent from
the status of the Manila share.&lt;/p&gt;
&lt;p&gt;Share attachment/detachment can only be done if the VM state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The operation to start a VM might fail if the attachment of an
underlying share fails or if the share is not in an inactive state.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In such scenarios, the instance will be marked as ERROR. Subsequent
attempts to start the VM will necessitate a hard reboot by the user,
in line with standard procedures for such kind of situations. This
error handling will be centralized and managed by the compute host.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Mount operation will be done when the share is not mounted on the compute host.
If a previous share would have been mounted on the compute host for another
server, then it will attempt to mount it and a warning will be logged that
the share was already mounted.&lt;/p&gt;
&lt;p&gt;Umount operation will be really done when the share is mounted and not used
anymore by another server.&lt;/p&gt;
&lt;p&gt;With the above mount and umount operation, the state is stored in memory and
do not require a lookup in the database.&lt;/p&gt;
&lt;p&gt;The share will be mounted on the compute host using read/write mode.
Read-only will not be supported as a share could not be mounted read-only
and read/write at the same time. If the user wants to mount the share
read-only, it will have to do it in the VM fstab.&lt;/p&gt;
&lt;p&gt;Instance Deletion Processes:&lt;/p&gt;
&lt;p&gt;Standard Deletion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;During a normal deletion process on the compute side, both the unmount
and Manila policy removal are attempted.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If both operations succeed, the corresponding share mapping is also
removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If either the unmount or policy removal fails, the instance
itself is deleted, but a share mapping record may remain in the database.
A future enhancement will include a periodic task designed to unmount,
remove the policy, and clean up any leaked share mappings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Local Deletion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the VM is marked as DELETED in the database due to unavailable
compute during the delete request, no unmounting or Manila policy removal
occurs via the API.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Once the compute is operational again, it identifies instances marked
as DELETED that have not yet been cleaned up. During the initialization
of the instance, the compute attempts to complete the deletion process,
which includes unmounting the share and removing the access policy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If these actions are successful, the share mapping will be removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If either action fails, the deletion remains incomplete; however, the
compute’s startup process continues unaffected, and the error is merely
logged. For security reasons, it’s crucial not to retain the mount,
necessitating a retry mechanism for cleanup. This situation parallels
the standard deletion scenario and requires a similar periodic task
for resolution.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Manila share removal issue:&lt;/p&gt;
&lt;p&gt;An issue was identified in the Zed cycle, a share being used by instances
could be removed by the user.
As a result, the instances would loose access to the data and might cause
difficulties in removing the missing share and fixing the instance.&lt;/p&gt;
&lt;p&gt;A solution was identified with the Manila team to attach metadata to the share
access policy that will lock the share and prevent its deletion until
the lock is not removed.&lt;/p&gt;
&lt;p&gt;This solution was implemented in the Antelope cycle.
The proposal here will use the lock mechanism in Nova.&lt;/p&gt;
&lt;p&gt;Instance metadata:&lt;/p&gt;
&lt;p&gt;Add instance shares in the instance metadata.
Extend DeviceMetadata with ShareMetadata object containing &lt;cite&gt;shareId&lt;/cite&gt; and
&lt;cite&gt;tag&lt;/cite&gt; used to mount the virtiofs on an instance by the user.
See &lt;a class="reference internal" href="#dalmatian-other-end-user-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PROJECT_ADMIN will be able to see details of the attachment id and export
location stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance must be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance should have the required capabilities to enable
virtiofs (see above).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This API operates asynchronously. Consequently, the share_mapping is defined
and it status is marked as “attaching” in the database.&lt;/p&gt;
&lt;p&gt;In the background, the compute node will request Manila to grant access to
the share and lock it for nova usage. Once this process is complete, the
share status is changed to inactive.  It’s important to note that locking
the share also restricts visibility to users to prevent any inadvertent
exposure of internal data.&lt;/p&gt;
&lt;p&gt;Following that, when the VM is powered on, the share will be mounted
onto the compute node and designated as active provided there are no
errors. Conversely, when the VM is powered off, the share will be unmounted
from the compute node and marked as inactive, again, if there are no errors
encountered.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter in the request body, when not
provided it will be the shareId(UUID) as always provided in the request.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; if povided by the user must be an ASCII string with a maximum
lenght of 64 bytes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance must be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;This API functions asynchronously, leading to the share_mapping status being
marked as detaching.&lt;/p&gt;
&lt;p&gt;Concurrently, the compute system conducts a verification to see if the
share is no longer being utilized by another instance. If found unused,
it requests Manila to unlock the share and deny access.&lt;/p&gt;
&lt;p&gt;To maintain consistent logic for both NFS and CephFS, we currently remove
the access policy only after the last user has unmounted the share across
all compute systems. While NFS could potentially implement an access policy
based on per-compute IP, CephFS currently employs an access token specific to
each Nova user. In the future, we may explore utilizing a CephFS user/token
that is specific to each Nova instance on each compute system.&lt;/p&gt;
&lt;p&gt;Two checks are necessary:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To unmount, it’s important to verify whether any other virtual machines
are using the share on the same compute system. This mechanism is already
implemented by the driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For removing the access policy, we need to
ensure that no compute system is currently using the share.
Once this process is finalized, the association of the share is eliminated
from the database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Primary key autoincrement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attaching&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detaching&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inactive&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within
the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the
underlying host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_proto&lt;/span&gt;&lt;/code&gt; - The Shared File Systems protocol (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NFS&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CEPHFS&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;The database field &lt;cite&gt;status&lt;/cite&gt; and &lt;cite&gt;share_proto&lt;/cite&gt; values will not be enforced
using enums allowing future changes and avoid database migrations.
However, to make code more robust, enums will be defined on the object fields.&lt;/p&gt;
&lt;p&gt;Fields containing text will use String and not Text type in the database schema
to limit the column width and be stored inline in the database.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to mount the
share to the host and the host filesystem location should
not be logged by Nova and only accessible by default through the API by admins.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One to add new notifications for share attach and share detach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One to extend the instance update notification with the share mapping
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Share mapping in the instance payload will be optional and controlled via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include_share_mapping&lt;/span&gt;&lt;/code&gt; notification configuration parameter. It will be
disabled by default.&lt;/p&gt;
&lt;p&gt;Proposed payload for attached and detached notification will be the same as
the one returned by the show command with admin rights.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Proposed instance payload for instance updade, will be the list of share
attached to this instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-ffffffffffff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7987"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server2.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="dalmatian-other-end-user-impact"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Users could use the instance metadata to discover and auto mount the share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.
While there will be near local performance between the vm and host,
the actual performance will be limited by the network performance of
the network file share protocol and hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and capability traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;p&gt;A new DB migration constraint to prevent a share to be attached more
than once will be introduced.
Because the share_mapping table was never able to be utilized in production,
it is proposed that the table be dropped and then reconstructed with the
updated constraint. This approach will help standardize the process across
all database systems, as sqlite does not allow altering table constraints,
requiring the table to be recreated.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (initial contributor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new capability traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated and reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 22 Mar 2024 00:00:00 </pubDate></item><item><title>Enforce remote console session timeout</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/enforce-remote-console-session-timeout.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/enforce-remote-console-session-timeout"&gt;https://blueprints.launchpad.net/nova/+spec/enforce-remote-console-session-timeout&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently providing vnc console consists 3 parts:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;1 - Working Conosle for Nova instance.&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Once a Nova instance is created in the hypervisor, the hypervisor
itself provides a console without the need for additional installations
within the instnace (as per nova.conf).
To access the console, operators can use &lt;cite&gt;virsh console instance-xxx&lt;/cite&gt;,
which provides a serial console (character terminal access) and prompts
the instance login console.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;2 - Provide console access outside compute node via browser.&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;When user creates a console URL to access console via a web browser.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;$ openstack console URL show &amp;lt;vm&amp;gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;The cmd calls Nova API, the Nova API in turn, communicates through the
RPC to compute service, which returns a new URL for connecting to an
existing console.&lt;/p&gt;
&lt;p&gt;The command does not create a new console but rather generates
a URL for connecting to the existing console. This URL includes a token
for authentication via the proxy.&lt;/p&gt;
&lt;p&gt;This URL can be used to connect to the Nova instance console. The console
token is used to athenticate with the proxy, enabling new sessions to be
established until the token ttl expires.
The existing session continue to function even after token expiration until
the tcp connection is closed.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;3- Controller’s Nova Proxy: Bridging Client Browser and Compute Node&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;When a user connects to the provided URL via a browser, the Nova Proxy acts
as an intermediary. It establishes a WebSocket connection to the hypervisor
and proxies the console to the client.
For VNC consoles, the Nova Proxy serves an HTML page with a JavaScript
application that runs at client side in the user’s browser, providing
a VNC client experience.
In the case of a serial console, the Nova Proxy provides a direct
WebSocket connection without a pre-built client, allowing users to
create their own clients that interact with the WebSocket.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                            &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Compute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;virt&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;======&amp;gt;&lt;/span&gt;                                       &lt;span class="o"&gt;&amp;lt;======&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                                &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

                              &lt;span class="n"&gt;Controller&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;                                 &lt;span class="n"&gt;Compute&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Today, there is no mechanism in place to enforce the termination of a console
session when the console token expires. Users can continue to access the
console beyond the token expiration, and there is a need to address this
behavior to enhance security measures.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to make sure that with console authentication TTL,
console sessions get closed too, and hence the user should get
disconnected from the console automatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Implement a timer mechanism to automatically close target socket connection
from server side when token has expired based on exact token expiration
time. This will interrupt the real time console session on client side
browser or other application.&lt;/p&gt;
&lt;p&gt;Also, introduce a new consoleauth config option &lt;cite&gt;enforce_session_timeout&lt;/cite&gt;
that allows operator to enable or disable the token expiry check.
The default setting is disabled, with &lt;cite&gt;False&lt;/cite&gt; as its default value. This
gives flexibility to exisiting console user based on their specific
requirements.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Client-side polling to check for token expiration. But as there are
many vnc clients, its better to address the issue at server side
to ensure a consistency in session timeout.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This change enable strict time span for console access requiring,
While it doesn’t inherently enhance the safety of console access,
it ensures that users must reauthenticate after a specified time
period.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new optional config option will be added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;auniyal&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;auniyal&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update Nova webproxy code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;funtional&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;release notes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>Ironic Shards</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/ironic-shards.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ironic-shards"&gt;https://blueprints.launchpad.net/nova/+spec/ironic-shards&lt;/a&gt;&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The deprecation for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ironic]\peer_list&lt;/span&gt;&lt;/code&gt; config option,
explained below in &lt;a class="reference internal" href="#config-changes-and-deprecations"&gt;Config changes and Deprecations&lt;/a&gt;, was
landed in 2023.2 (Bobcat). The rest of the feature was reverted
due to a late-discovered bug and is being re-submitted in 2024.1
(Caracal).&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova’s Ironic driver involves a single nova-compute service managing
many compute nodes, where each compute node record maps to an Ironic node.
Some deployments support 1000s of ironic nodes, but a single nova-compute
service is unable to manage 1000s of nodes and 1000s of instances.&lt;/p&gt;
&lt;p&gt;Currently we support setting a partition key, where nova-compute only
cares about a subset of ironic nodes, those associated with a specific
conductor group. However, some conductor groups can be very large,
servered by many ironic-conductor services.&lt;/p&gt;
&lt;p&gt;To help with this, Nova has attempted to dynamically spread ironic
nodes between a set of nova-compute peers. While this work some of
the time, there are some major limitations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;when one nova-compute is down, only unassigned ironic nodes can
move to another nova-compute service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;i.e. when one nova-compute is down, all ironic nodes with nova instances
associated with the down nova-compute service are unable to be
managed, i.e. reboot will fail&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;moreover, when the old nova-compute comes back up, which might take
some time, there are lots of bugs as the hash ring slowly rebalances.
In part because every nova-compute fetches all nodes, in a large enough
cloud, this can take over 24 hours.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This spec is about tweaking the way we shard Ironic compute nodes.
We need to stop violating deep assumptions in the compute manager
code by moving to a more static ironic node partitions.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Any users of the ironic driver that have more than one
nova-compute service per conductor group should move to an
active-passive failover mode.&lt;/p&gt;
&lt;p&gt;The new static sharding will be of paritcular interest for clouds
with ironic conductor groups that are greater than around
1000 baremetal nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We add a new configuration option:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;[ironic] shard_key&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, there will be no shard_key set, and we will continue to
expose all ironic nodes from a single nova-compute process.
Mostly, this is to keep things simple for smaller deployments,
i.e. when you have less than 500 ironic nodes.&lt;/p&gt;
&lt;p&gt;When the operator sets a shard_key, the compute-node process will
use the shard_key when querying a list of nodes in Ironic.
We must never try to list all Ironic nodes when
the Ironic shard key is defined in the config.&lt;/p&gt;
&lt;p&gt;When we look up a specific ironic node via a node uuid or
instance uuid, we should not restrict that to either the shard key
or conductor group.&lt;/p&gt;
&lt;p&gt;Similar to checking the instance uuid is still present on the Ironic
node before performing an action, or ensuring there is no instance uuid
before provisioning, we should also check the node is in the correct
shard (and conductor group) before doing anything with that Ironic node.&lt;/p&gt;
&lt;section id="config-changes-and-deprecations"&gt;
&lt;h3&gt;Config changes and Deprecations&lt;/h3&gt;
&lt;p&gt;We will keep the option to target a specific conductor group,
but this option will be renamed from partition_key to conductor_group.
This is addative to the shard_key above, the target ironic nodes are
those in both the correct &lt;cite&gt;shard_key&lt;/cite&gt; and the correct &lt;cite&gt;conductor_group&lt;/cite&gt;,
when both are configured.&lt;/p&gt;
&lt;p&gt;We will deprecate the use of the &lt;cite&gt;peer_list&lt;/cite&gt;.
We should log a warning when the hash ring is being used,
i.e. when it has more than one member added to the hash ring.&lt;/p&gt;
&lt;p&gt;In addtion, we need the logic that tries to move Compute Nodes
to never work unless the peer_list is larger than one. More details
in the data model impact section.&lt;/p&gt;
&lt;p&gt;When deleting a ComputeNode object, we need to have the driver
confirm that is safe. In the case of Ironic we will check to see if
the configured Ironic has a node with that uuid, searching across all
conductor groups and all shard keys. When the ComputeNode object is not
deleted, we should not delete the entry in placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="nova-manage-move-ironic-node"&gt;
&lt;h3&gt;nova-manage move ironic node&lt;/h3&gt;
&lt;p&gt;We will create a new nova-manage command:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
    &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This command will do the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Find the ComputeNode object for this ironic-node-uuid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if the ComputeNode type does not match the ironic driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the related Service object for the above ComputeNode
(i.e. the host)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if the service object is not reported as down, and
has not also been put into maintanance. We do not require
forced down, because we might only be moving a subset of
nodes associated with this nova-compute service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the Service object for the destination service host exists&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find all non-deleted instances for this (host,node)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if there is more than 1 non-deleted instance found.
It is OK if we find zero or 1 instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In one DB transaction:
move the ComputeNode object to the destination service host and
move the Instance (if there is one) to the destination service host&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above tool is expected to be used as part of this wider process
of migrating from the old peer_list to the new shard key. There are
two key scearios (although the tool may help operator recover from
other issues as well):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;moving from a peer_list to a single nova-compute&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;moving from peer_list to shard_key, while keeping multiple nova-compute
proccesses (for a single conductor group)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="migrate-from-peer-list-to-single-nova-compute"&gt;
&lt;h3&gt;Migrate from peer_list to single nova-compute&lt;/h3&gt;
&lt;p&gt;Small deployments (i.e. less than 500 ironic nodes)
are recommended to move from a peer_list of, for example,
three nova-compute services, to a single nova-compute service.
On failure of the nova-compute service, operators can either manually start
the processes on a new host, or use an automatic active-passive HA scheme.&lt;/p&gt;
&lt;p&gt;The process would look something like this:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ironic and nova both default to an empty_shard key by default,
such that all ironic nodes are in the same default shard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;start a new nova-compute service running the ironic driver,
ideally with a syntheic value for &lt;cite&gt;[DEFAULT]host&lt;/cite&gt; e.g. &lt;cite&gt;ironic&lt;/cite&gt;
This will log warnings about the need to use the nova-compute
migration tool before being able to manage any nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop all existing nova-compute services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mark them as forced-down via the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now loop around all ironic nodes and call this, assuming your
nova-compute service has its host value of just &lt;cite&gt;ironic&lt;/cite&gt;:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service ironic&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The periodic tasks in the new nova-compute service will gradually
pick up the new ComputeNodes, and will start being able to recieve
commands such a reboot for all the moved instances.&lt;/p&gt;
&lt;p&gt;While you could start the new nova-compute service after
having migrated all the ironic compute nodes, but that would
lead to higher downtime during the migration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migrate-from-peer-list-to-shard-key"&gt;
&lt;h3&gt;Migrate from peer_list to shard_key&lt;/h3&gt;
&lt;p&gt;The proccess to move from the hash key based peer_list to the static
shard_key from ironic is very similar to the above process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Set the shard_key on all your ironic nodes, such that you can spread
the nodes out between your nova-compute processes,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start your new nova compute processes, one for each &lt;cite&gt;shard_key&lt;/cite&gt;,
possibly setting a synthetic &lt;cite&gt;[DEFAULT]host&lt;/cite&gt; value that matches the
&lt;cite&gt;my_shard_key&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shutdown all the older nova-compute processs with &lt;cite&gt;[ironic]peer_list&lt;/cite&gt; set&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark those older services as in maintainance via the Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each shard_key in Ironic, work out which service host you have mapped
each one to above, then run this for each ironic node uuid in the shard:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service my_shard_key&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the old services via the Nova API, now there are no instances
or compute nodes on those services&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While you could start the new nova-compute services after the migration,
that would lead to a slightly longer downtime.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="adding-new-compute-nodes"&gt;
&lt;h3&gt;Adding new compute nodes&lt;/h3&gt;
&lt;p&gt;In general, there is no change when adding nodes into existing
shards.&lt;/p&gt;
&lt;p&gt;Similarly, you can add a new nova-compute process for a new shard
and then start to fill that up with nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="move-an-ironic-node-between-shards"&gt;
&lt;h3&gt;Move an ironic node between shards&lt;/h3&gt;
&lt;p&gt;When removing nodes from ironic at the end of their life, or
adding large numbers of new nodes, you may need to rebalance
the shards.&lt;/p&gt;
&lt;p&gt;To move some ironic nodes, you need to move the nodes in
groups associated with a specific nova-compute process.
For each nova-compute and the associated ironic nodes you
want to move to a different shard you need to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Shutdown the affected nova-compute process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put nova-compute services into in maintanance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Ironic API update the shard key on the Ironic node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now move each ironic node to the correct new nova-compute
process for the shard key it was moved into:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service my_shard_key&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now unset maintanance mode for the nova-compute,
and start that service back up&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="move-shards-between-nova-compute-services"&gt;
&lt;h3&gt;Move shards between nova-compute services&lt;/h3&gt;
&lt;p&gt;To move a shard between nova-compute services, you need to
replace the nova-compute process with a new one:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ensure the destination nova-compute is configured with the
shard you want to move, and is running&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop the nova-compute process currently serving the shard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;force-down the service via the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for each ironic node uuid in the shard call nova-manage
to move it to the new nova-compute process&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could require nova-compute processes to be explicitly forced down,
before allowing the nova-manage to move the ironic nodes about,
in a similar way to evacuate.
But this creates problems when trying to re-balance shards as you
remove nodes at the end of their life.&lt;/p&gt;
&lt;p&gt;We could consider a list of shard keys, rather than a single shard key
per nova-compute. But for this first version, we have chosen the simpler
path, that appears to have few limitations.&lt;/p&gt;
&lt;p&gt;We could attempt to keep fixing the hash ring recovery within the ironic
driver, but its very unclear what will break next due to all the deep
assumptions made about the nova-compute process. The specific assumptions
include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;when nova-compute breaks, its usually the hypervisor hardware that
has broken, which includes all the nova servers running on that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all locking and management of a nova server object is done by the
currently assigned nova-compute node, and this is only ever changed
by explict move operations like resize, migrate, live-migration
and evacuate. As such we can use simple local locks to ensure
concurrent operations don’t conflict, along with DB state checking.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A key thing we need to ensure is that ComputeNode objects are only
automatically moved between service objects when in legacy hash ring mode.
Currently, this only happens for unassigned ComputeNodes.&lt;/p&gt;
&lt;p&gt;In this new explicit shard mode, only nova-manage is able to move
ComputeNode objects. In addtion, nova-manage will also move associated
instances. However, similar to evacuate, this will only be allowed
when the currently associated service is forced down.&lt;/p&gt;
&lt;p&gt;Note, this applies when a nova-compute finds a ComputeNode that is should
own, but the Nova database says its already owned by a difference service.
In this scenario, we should log a warning to the operator
to ensure they have migrated that ComputeNode from its old location
before this nova-compute service is able to manage it.&lt;/p&gt;
&lt;p&gt;In addition, we should ensure we only delete a ComputeNode object
when the driver explictly says its safe to delete. In the case of
the Ironic driver, we should ensure the node no longer exists in
Ironic, being sure to search across all shards.&lt;/p&gt;
&lt;p&gt;This is all very related this spec on robustfying
the Compute Node and Service object relationship:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/853837"&gt;https://review.opendev.org/c/openstack/nova-specs/+/853837&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will experience a more reliable Ironic and Nova integration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;It should help users more easily support large ironic deployments
integrated with Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;We will rename the “partition_key” configuration to be expliclity
“conductor_group”.&lt;/p&gt;
&lt;p&gt;We will deprecate the peer list key. When we start up and see
anything set, we ommit a warning about the bugs in using this
legacy auto sharding, and recomend moving to the explicit sharding.&lt;/p&gt;
&lt;p&gt;There is a new &lt;cite&gt;shard_key&lt;/cite&gt; config, as descirbed above.&lt;/p&gt;
&lt;p&gt;There is a new nova_manage CLI command to move Ironic compute nodes
on forced-down nova-compute services to a new one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For those currenly using peer_list, we need to document how they
can move to the new sharding approach.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;JayF&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Feature liaison: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;rename conductor group partition key config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;deprecate peer_list config, with warning log messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add compute node move and delete protections, when peer_list not used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add new shard_key config, limit ironic node list using shard_key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add nova-manage tool to move ironic nodes between compute services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;document operational processes around above nova-manage tool&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The deprecation of the peer list can happen right away.&lt;/p&gt;
&lt;p&gt;But the new sharding depends on the Ironic shard key getting added:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/ironic-specs/+/861803"&gt;https://review.opendev.org/c/openstack/ironic-specs/+/861803&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally we add this into Nova after robustify compute node has landed:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/842478"&gt;https://review.opendev.org/c/openstack/nova/+/842478&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We need some functional tests for the nova-manage command to ensure
all of the safety guards work as expected.&lt;/p&gt;
&lt;p&gt;We need to ensure a tempest test exists which has multiple shards, with
only one shard containing valid, functional Ironic nodes. Then, ensure
that only the valid nodes are scheduled to.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A lot of docs needed for the Ironic driver on the operational
procedures around the shard_key.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed, Partially implemented&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>Move to using Libvirt device aliases</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/libvirt-dev-alias.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-dev-alias"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-dev-alias&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently we identify devices in Libvirt guest XML by a variety of methods,
which differs based on the device type (at least). Libvirt now provides a
device alias mechanism by which we can tie virtual guest devices to an
identifier we can use to look them up in a stable and generic way. Nova
should move to using that, which will increase consistency, decrease some
complexity, and also work around some issues with our current strategy.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova currently looks up guest devices in XML for attach/detach and other
modifications using a variety of methods. For example, disk devices use
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;serial&lt;/span&gt;&lt;/code&gt; property to identify them uniquely. However, libvirt and
qemu do not support setting this property on all disk device types, which
means Nova cannot use that to look up disk devices in a generic way. Further,
if we have multiple network interfaces with the same MAC address, using that
as a unique identifier is not sufficient.&lt;/p&gt;
&lt;p&gt;Example volume attachment:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'block'&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'disk'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'qemu'&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'raw'&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'none'&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'native'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/dev/sda'&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'5'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;backingStore&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'vdb'&lt;/span&gt; &lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'virtio'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ada5af06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;300e-4&lt;/span&gt;&lt;span class="n"&gt;d07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;931&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;cc2bff8a8a9&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'virtio-disk1'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pci'&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0000'&lt;/span&gt; &lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x00'&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x07'&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a developer, I want Nova to be able to manage libvirt guest devices in a
stable and consistent way.&lt;/p&gt;
&lt;p&gt;As a deployer, I want Nova to support things like SCSI LUN passthrough, which
does not support setting the device serial in libvirt.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova’s libvirt driver should move to using the device alias mechanism
&lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; for identifying all types of devices that are attach- or
detach-able. For devices like volumes and network interfaces, the
volume or port UUID should be used.  For other devices, some other
stable identifier that correlates to something in Nova or another
service’s database is required. Libvirt has specific requirements for
the format of the alias, which must be followed. However, for most
devices that use a UUID as the primary identifier, we should be able
to embed that within the alias.&lt;/p&gt;
&lt;p&gt;This is what the above disk example would look like with a
nova-specified alias:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'block'&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'disk'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'qemu'&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'raw'&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'none'&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'native'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/dev/sda'&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'5'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;backingStore&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'vdb'&lt;/span&gt; &lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'virtio'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ada5af06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;300e-4&lt;/span&gt;&lt;span class="n"&gt;d07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;931&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;cc2bff8a8a9&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ua-ada5af06-300e-4d07-931d-3cc2bff8a8a9'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pci'&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0000'&lt;/span&gt; &lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x00'&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x07'&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0x0'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could keep what we have and continue to not support disk devices that do not
support using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;serial&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We could maintain our own mapping in our database for those device types.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Nova’s own data model is not affected by this and this is limited to
nova-compute and the libvirt driver. However, the libvirt XML data that we
currently maintain will need to change (and existing instances migrated) to
set the device aliases accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;End users can currently request SCSI LUN-based disk device mapping, but it does
not work because we are unable to specify the device serial in that
configuration. After this change, that existing mechanism will begin to work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No major performance impact to Nova itself, although looking up
devices by alias will be easier and less computationally
intense. Further a detach-by-alias routine &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; is provided by
libvirt which may be significantly easier than what we currently need
to do by generating and providing an XML blob for detach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The libvirt driver will ultimately be simpler after this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The only upgrade impact comes from migrating existing instance XML documents
to specify the device alias. Because we may be migrating instances to/from
older nodes, we should retain compatibility with alias-less XMLs for some time
to come.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;kashyap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;dansmith&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enable setting and parsing the device alias on disk, interface, and pci
devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Actually set those device aliases in the various parts of the driver that
create those configs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the code that looks up devices by device-specific identifiers prefer the
alias and fall back to the old way&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrate existing instance XMLs on startup when device aliases are missing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Libvirt 3.9.0: &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#devices"&gt;https://libvirt.org/formatdomain.html#devices&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Existing devstack jobs should provide sufficient coverage other than the unit
and functional coverage that will be added. Potentially enabling (and using)
the LUN passthrough attachment mechanism would be beneficial, but that is
somewhat beyond the scope of this effort which is just changing the enumeration
behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;There really is not much in the way of documentation impact because this
should be transparent to the operators and users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Libvirt’s device XML specification: &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#devices"&gt;https://libvirt.org/formatdomain.html#devices&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Libvirt’s detach-by-alias function: &lt;a class="reference external" href="https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainDetachDeviceAlias"&gt;https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainDetachDeviceAlias&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>Add maxphysaddr support for Libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/libvirt-maxphysaddr-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-maxphysaddr-support"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-maxphysaddr-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint propose new flavor extra_specs and image properties to control
the physical address bits of vCPUs in Libvirt guests.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When booting a guest with 1TB+ RAM, the default physical address bits are
too small and the boot fails &lt;a class="footnote-reference brackets" href="#id11" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. So a knob is needed to specify the
appropriate physical address bits.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Booting a guest with large RAM.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In Libvirt v8.7.0+ and QEMU v2.7.0+, physical address bits can be specified
with following XML elements &lt;a class="footnote-reference brackets" href="#id12" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id13" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. The former means to adopt any physical
address bits, the latter means to adopt the physical address bits of the
host CPU.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;maxphysaddr&lt;/span&gt; &lt;span class="pre"&gt;mode='emulate'&lt;/span&gt; &lt;span class="pre"&gt;bits='42'/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;maxphysaddr&lt;/span&gt; &lt;span class="pre"&gt;mode='passthrough'/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="flavor-extra-specs-and-image-properties"&gt;
&lt;h3&gt;Flavor extra_specs and image properties&lt;/h3&gt;
&lt;p&gt;Here I suggest the following two for flavor extra_specs and image properties.
Of course, if these are omitted, the behavior is the same as before.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode&lt;/span&gt;&lt;/code&gt; can be either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;emulate&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passthrough&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt; takes a positive integer value.
Only meaningful and must be specified if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the overall flavor extra_specs look like the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maxphysaddr_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;emulate&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maxphysaddr_bits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Also the same, but the overall image properties look like the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw_maxphysaddr_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;emulate&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw_maxphysaddr_bits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="nova-scheduler-changes"&gt;
&lt;h3&gt;Nova scheduler changes&lt;/h3&gt;
&lt;p&gt;Nova scheduler also needs to be modified to take these two properties
into account.&lt;/p&gt;
&lt;section id="hw-maxphysaddr-mode"&gt;
&lt;h4&gt;hw:maxphysaddr_mode&lt;/h4&gt;
&lt;p&gt;There can be a mix of supported and unsupported hosts depending
on Libvirt and QEMU versions. So add new traits
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_PASSTHROUGH&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt;
to check the scheduled host supports this feature.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_ADDRESS_SPACE_PASSTHROUGH=required&lt;/span&gt;&lt;/code&gt; is automatically added
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; is specified in flavor extra_specs
or image properties.
And same for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. This can be implemented inside
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;from_request_spec&lt;/span&gt;&lt;/code&gt; method of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ResourceRequest&lt;/span&gt;&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;Passthrough and emulate modes have different properties. So let’s consider
the two separately.&lt;/p&gt;
&lt;p&gt;The case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt;. In this case,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt; is a requirement, which is already taken
into account in nova scheduling, and no additional modifications are
required in this proposal. It is not guaranteed whether the instance
can be migrated by nova. So the admin needs to make sure that targets
of cold and live migration have similar hardware and software.
This restriction is similar for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. In nova scheduling,
it is necessary to check that the hypervisor supports at least
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt;. Numerical comparison is implemented differently
for flavor extra_specs and image properties, so it is divided into two cases.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="hw-maxphysadr-bits"&gt;
&lt;h4&gt;hw:maxphysadr_bits&lt;/h4&gt;
&lt;p&gt;The maximum number of bits supported by hypervisor can be obtained by using
libvirt capabilities &lt;a class="footnote-reference brackets" href="#id14" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt; is set to flavor extra_specs,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; can be used to compare the number
of bits in scheduling.  For example, this can be accomplished by adding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;capabilities:cpu_info:maxphysaddr:bits&amp;gt;=42&lt;/span&gt;&lt;/code&gt; automatically.&lt;/p&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_maxphysaddr_bits&lt;/span&gt;&lt;/code&gt; is set to image properties, perform a numeric
comparison with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagePropertiesFilter&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cold migration and live migration can also be realized with these
filter and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt; trait.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Before the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxphysaddr&lt;/span&gt;&lt;/code&gt; option was introduced into Libvirt, it was specified
as a workaround with the QEMU comanndline parameter. But this alternative is
not allowed in nova.&lt;/p&gt;
&lt;p&gt;Also, some Linux distributions may have machine types with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host-phys-bits=true&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id15" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. For example, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc-i440fx-bionic-hpb&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc-q35-bionic-hpb&lt;/span&gt;&lt;/code&gt;. However, this alternative has following two issues and
cannot be adopted for general-purpose use cases.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ubuntu package maintainers are applying a patch to QEMU &lt;a class="footnote-reference brackets" href="#id16" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. It means this
is not included in vanilla QEMU and is not available in other distributions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is only the case for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; and does not
include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. Since
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; requires &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt;
to be used &lt;a class="footnote-reference brackets" href="#id17" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, this alternative cannot be used with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=custom&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-model&lt;/span&gt;&lt;/code&gt;. So, this alternative is not sufficient for
a cloud with many different CPU models.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As for scheduling, placement does not currently support numeric traits,
so the maximum number of bits supported by hypervisor cannot be checked
by this mechanism. Numeric comparisons can also be performed with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;JsonFilter&lt;/span&gt;&lt;/code&gt;. However, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;JsonFilter&lt;/span&gt;&lt;/code&gt; appears to be vulnerable to changes in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; and its child attributes, which is mentioned as a warning &lt;a class="footnote-reference brackets" href="#id20" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;10&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.
So this spec employs &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagePropertiesFilter&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators should specify appropriate flavor extra_specs or image properties
as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As described earlier, the new traits &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_PASSTHROUGH&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt; signal if the upgraded compute nodes support
this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nmiki&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;This spec is addressed across multiple dev cycles.
The merged and missing items are shown below, respectively.&lt;/p&gt;
&lt;section id="merged-items"&gt;
&lt;h4&gt;Merged Items&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new traits to check Libvirt and QEMU versions &lt;a class="footnote-reference brackets" href="#id18" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id19" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="missing-items"&gt;
&lt;h4&gt;Missing Items&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new guest configs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fileds in nova/api/validation/extra_specs/hw.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fileds in nova/objects/image_meta.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fields in LibvirtConfigCPU in nova/virt/livbirt/config.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxphysaddr&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info&lt;/span&gt;&lt;/code&gt; in nova/virt/libvirt/driver.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs and release notes for new flavor extra_specs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysadar_bits&lt;/span&gt;&lt;/code&gt; numeric comparison
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_maxphysaddr_bits&lt;/span&gt;&lt;/code&gt; numeric comparison
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagePropertiesFilter&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Libivrt v8.7.0+.
QEMU v2.7.0+.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add the following unit tests:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;check that proposed flavor extra_specs are properly validated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that proposed image properties are properly validated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that intended XML elements are output&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that traits are properly added and used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that new field in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; is property
added and used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that new field in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImagePropertiesFilter&lt;/span&gt;&lt;/code&gt; is property
added and used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;For operators, the documentation describes what proposed flavor extra_specs
and image properties mean and how they should be set.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1769053"&gt;https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1769053&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/news.html#v8-7-0-2022-09-01"&gt;https://libvirt.org/news.html#v8-7-0-2022-09-01&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/commit/1c1a7cdd4096c59fb0c374529e1e5aea8d43ee9c"&gt;https://github.com/libvirt/libvirt/commit/1c1a7cdd4096c59fb0c374529e1e5aea8d43ee9c&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id14" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatcaps.html#examples"&gt;https://libvirt.org/formatcaps.html#examples&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://cpaelzer.github.io/blogs/005-guests-bigger-than-1tb/"&gt;https://cpaelzer.github.io/blogs/005-guests-bigger-than-1tb/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/commit/?id=6ba8b5c843d405e1b067dc8b98ecb8545af78a2b"&gt;https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/commit/?id=6ba8b5c843d405e1b067dc8b98ecb8545af78a2b&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id17" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/blob/v8.7.0/src/qemu/qemu_validate.c#L346-L351"&gt;https://github.com/libvirt/libvirt/blob/v8.7.0/src/qemu/qemu_validate.c#L346-L351&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id18" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/871226"&gt;https://review.opendev.org/c/openstack/os-traits/+/871226&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id19" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/873221"&gt;https://review.opendev.org/c/openstack/nova/+/873221&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id20" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;10&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/scheduling.html#jsonfilter"&gt;https://docs.openstack.org/nova/latest/admin/scheduling.html#jsonfilter&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id21"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>Mediated device live migration with libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/libvirt-mdev-live-migrate.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-mdev-live-migrate"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-mdev-live-migrate&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Starting with libvirt-8.6.0, QEMU-8.1.0 and Linux kernel 5.18.0, guests using
mediated devices can be live migrated by using a target mediated device using
the same mediated device type (and we don’t need to unplug/plug the mdevs).
Now, we need to support this for Nova, which means that Nova should provide
a target mediated device UUID (that exists) to the source compute service by
the pre-live-migrating call so the target XML created by the source would use
it.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;For the moment, this is not possible to live-migrate an instance if it uses a
mediated device as the target wouldn’t create it. You can only for the moment
cold-migrate the instance or do other move operations like shelve.
Fortunately, libvirt 8.5.0 now supports to live-migrate a guest by using a
target mediated device uuid in the target XML so we want to directly support
this in Nova.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to move my instance using a vGPU to another host without
the user being aware of it.&lt;/p&gt;
&lt;p&gt;As an operator, I want to make sure I will only live-migrate by using the same
mediated device type between the source and the target.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In order to succesfully live-migrate a guest with libvirt, you need to modify
the target guest XML to use another mediated device using the same mdev
(mediated device) type.
In order to do it, we propose the following workflow :&lt;/p&gt;
&lt;p&gt;First, during the conductor compatibility checks, we will verify the types
compatibility on the destination and we will claim for a specific list of
target mediated devices (either to be created or just kept reserved) this way :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;check_can_live_migrate_source()&lt;/span&gt;&lt;/code&gt; (run on the source) will check the
libvirt version of the source and fail by raising a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationPreCheckError&lt;/span&gt;&lt;/code&gt; if the version if below the minimum required (see
&lt;a class="reference internal" href="#dependencies"&gt;Dependencies&lt;/a&gt;) and only if the instance has mediated devices. It will also
check the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; version returned by the destination and
will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationPreCheckError&lt;/span&gt;&lt;/code&gt; exception if older than the one
supporting the new fields (see both &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade Impact&lt;/a&gt; and
&lt;a class="reference internal" href="#data-model-impact"&gt;Data model impact&lt;/a&gt;).
Eventually, it will return the list of number of mdevs with their types back
to the target in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;driver’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_claim_migrate_data()&lt;/span&gt;&lt;/code&gt; will first check based on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object whether the libvirt version is below the
minimum required and then check whether those mdev types are compatible with
the types the target supports and will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationPreCheckError&lt;/span&gt;&lt;/code&gt; if
not. If successful, it will pick N (N being the requested number) of the
available mediated resources (either by creating new mdevs or taking existing
ones), based on the list that was passed thru &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt;, and
will persist that list of target mediated devices in some internal dictionary
field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt; instance, keyed by the instance UUID. We will
also pass those mdev uuids in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object that we
return over the wire to the source compute (we will call it later &lt;cite&gt;migrate
data object&lt;/cite&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;the current spec proposal is to use the existing NUMA-live-migration
related method called &lt;a class="reference external" href="https://github.com/openstack/nova/blob/45e2349408dd3b385217066a3c5a4c29d7bdd3a0/nova/virt/libvirt/driver.py#L9749"&gt;post_claim_migrate_data()&lt;/a&gt; but we could
create a specific new virt driver API method for this usage. This
will be discussed at implementation stage.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Later, once the source host starts the live-migration, we will update
the guest XML information with those mediated device UUIDs this way :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;in source’s driver &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_live_migration_operation()&lt;/span&gt;&lt;/code&gt; we lookup the migrate data
object we got and we update the target guest XML in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_updated_guest_xml()&lt;/span&gt;&lt;/code&gt; by getting those mediated device UUIDs from the
migrate data object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;in destination’s driver &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_live_migration_at_destination()&lt;/span&gt;&lt;/code&gt;, we delete
the mdevs tracked in the internal dictionary field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt;
instance by getting them from the dictionary which is keyed by the instance
UUID.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In case of any live migration abort or exception, the residue we only need to
clean up is basically the list of claimed mediated devices for the migration
that are set in the dictionary field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt; instance.
Accordingly, we propose to delete those records this way :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;if the exception occurred during pre-livemigration, it eventually calls on
destination &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rollback_live_migration_at_destination()&lt;/span&gt;&lt;/code&gt; depending on
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_live_migration_cleanup_flags()&lt;/span&gt;&lt;/code&gt; result. We will modify that verification
method to lookup whether we have mediated device UUIDs in the migrate data
object. Then, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rollback_live_migration_at_destination()&lt;/span&gt;&lt;/code&gt; will again look at
the dictionary to know which mediated devices to remove from the internal
dictionary in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if the exception happened during the live-migration (or if the operator asked
to abort it), then it eventually calls &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_rollback_live_migration()&lt;/span&gt;&lt;/code&gt; which
also calls &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rollback_live_migration_at_destination()&lt;/span&gt;&lt;/code&gt; like above, so it
would also remove the mdevs from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt; dictionary field.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a side note, the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/b64ecb0cc776bd3eced674b0f879bb23c8a4b486/nova/virt/libvirt/driver.py#L8361-L8394"&gt;current method&lt;/a&gt; we have for knowing which mediated
devices are used by instances will be modified to also take in account the list
of mediated devices that are currently set in internal directory field of the
LibvirtDriver we’ll be using for tracking which mdevs are claimed for
migrations.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Operators could continue to only do cold migrations or we could try to unplug
and then plug mediated devices during live-migration like we do at the moment
for SR-IOV VFs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;While we won’t describe the internal dictionary we would use in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt; class instance as this is just an implementation question, we
still need to explain which objects will be passed between computes RPC
services. As we said earlier, we need to augment the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt;
object.&lt;/p&gt;
&lt;p&gt;New fields will be added on that object (we can create a nested object if
people prefer):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;source_mdev_types:&lt;/span&gt; &lt;span class="pre"&gt;fields.DictOfStringsField()&lt;/span&gt;&lt;/code&gt; : dictionary where the key
is a source mediated device UUID and the value is its mdev type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;target_mdevs:&lt;/span&gt; &lt;span class="pre"&gt;fields.DictOfStringsField()&lt;/span&gt;&lt;/code&gt; : dictionary where the key is a
mediated device UUID of the source and the value a mdev UUID of the target,
implicitly matching the relationship between both for the live-migration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators wanting to use vGPU live-migration will need to support a recent
libvirt release, so they probably need to upgrade their OS. They will also need
to upgrade all their compute services, see &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade Impact&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Operators will need to make sure that the target computes are upgraded.
That said, given if the destination is not upgraded (and then doesn’t support
live migration), then it would return a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object
with a previous version. The source will know that the target doesn’t
support it and will accordingly raise &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationPreCheckError&lt;/span&gt;&lt;/code&gt; (we detailed
that above in &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt;).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sylvain-bauza&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtDriver&lt;/span&gt;&lt;/code&gt; internal dictionary&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;augment the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add the conductor checks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add the live-migration changes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;As said above, it requires :
- libvirt-8.6.0 and newer
- QEMU-8.1.0 and newer
- Linux kernel 5.18.0 and newer&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional tests are a very bare minimum but we’re actively chasing
the idea to use the &lt;a class="reference external" href="https://www.kernel.org/doc/html/v5.8/driver-api/vfio-mediated-device.html#using-the-sample-code"&gt;mtty kernel samples framework&lt;/a&gt; as a way to do some
Tempest testing that’s yet unwritten. We may need to build a custom kernel in
order to get the latest version of mtty that includes live-migration support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We’ll augment the usual &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/virtual-gpu.html"&gt;virtual GPU documentation&lt;/a&gt; with a section on how to
live-migrate and its requirements.&lt;/p&gt;
&lt;p&gt;As a note, the specific proprietary nVidia &lt;cite&gt;vfio-mdev&lt;/cite&gt; driver that provides
mediated device types and live-migration support currently has limitations and
doesn’t support pausing a VM and autoconverge feature. Besides, live-migration
downtime is very depending on the hardware so we somehow need to document those
hardware-specific knobs in some abstract manner in our upstream docs, pointing
as much as we can to the vendor documentation if existing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://qemu.readthedocs.io/en/v8.1.0/devel/vfio-migration.html"&gt;https://qemu.readthedocs.io/en/v8.1.0/devel/vfio-migration.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.qemu.org/ChangeLog/8.1#VFIO"&gt;https://wiki.qemu.org/ChangeLog/8.1#VFIO&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://lore.kernel.org/all/20220512233222.GH1343366@nvidia.com/T/"&gt;https://lore.kernel.org/all/20220512233222.GH1343366@nvidia.com/T/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(libvirt doc missing)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>List requested Availability Zones</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/list-requested-az.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/list-requested-az"&gt;https://blueprints.launchpad.net/nova/+spec/list-requested-az&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently server show and server list –long output, displays the
current AZ of the instance. That is, the AZ to which the host of
the instance belongs. There is no way to tell from this information
that whether the instance create request included an AZ or not.&lt;/p&gt;
&lt;p&gt;This implementation enables users to validate that their request for
Availability Zone was correctly processed and satisfied, by returning
back information, not only about current placement of the instance,
but also original request.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As of today, the server show and server list –long output, displays
the current AZ of the instance. That is, the AZ to which the host
of the instance belongs. There is no way to tell from this information
that whether the instance created request included an AZ or not.&lt;/p&gt;
&lt;p&gt;Also when cross_az_attach option is False and booting an instance
from volume, the instance can be pinned to AZ and in that case,
instance will be scheduled on host belonging to pinned AZ.&lt;/p&gt;
&lt;p&gt;Also when default_schedule_zone config option set to specific
AZ, in that case, instance would be pinned to that specific
AZ, and instance will be scheduled on host belonging to pinned AZ.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to know if the instance create request
asked for an AZ expliclity or not. And whether the requested AZ and
current AZ are both same or different.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The instances table from nova cell database does not have requested
availability zone information. The same can be get from request_specs
table in nova_api database.&lt;/p&gt;
&lt;p&gt;For server show output, use the existing get_by_instance_uuid method from
RequestSpec object and display it in the output.&lt;/p&gt;
&lt;p&gt;For server list –long output, implement a method get_by_instance_uuids for
RequestSpec object, which takes list of instance uuids of instances which
will be shown in the listed output and return a list of RequestSpec objects
of those instances.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;As an alternative, we could add the requested availability zone information in
instances table and when doing server list –long or server show use the data
from instances table only and display to users, but it would duplicate the
data in request_specs table as well as in instances table.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;For implementation, we need to add a method get_by_instance_uuids to
the RequestSpec object, which takes list of instance uuids as input and
returns list of RequestSpec objects of those instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This change will be done with a new microversion bump.&lt;/p&gt;
&lt;p&gt;Below are the two APIs that will be changed.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;server show api response will include availability zone requested
during server creation.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="o"&gt;...&lt;/span&gt;
          &lt;span class="s2"&gt;"pinned_availability_zone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
          &lt;span class="o"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;server list –long api response will include availability zone
requested during server creation.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="o"&gt;...&lt;/span&gt;
          &lt;span class="s2"&gt;"pinned_availability_zone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
          &lt;span class="o"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="o"&gt;...&lt;/span&gt;
          &lt;span class="s2"&gt;"pinned_availability_zone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
          &lt;span class="o"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be minor performance impact when user calls server list –long
because we will be adding another database call to get list of request_specs
of instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ratailor&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ratailor&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement API changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstackclient and openstacksdk needs to be updated to implement
this change.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functional tests (API samples)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The api-ref will be updated to reflect the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>VirtIO PackedRing Configuration support</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/implemented/virtio-packedring-configuration-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virtio-packedring-configuration-support"&gt;https://blueprints.launchpad.net/nova/+spec/virtio-packedring-configuration-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to expose the LibVirt &lt;cite&gt;packed&lt;/cite&gt; option that allows a
guest to negotiate support for the VirtIO packed-ring feature. This blueprint
is used to solicit community’s input.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;VM using a Virtio-net paravirtual network device uses Virtual queues (virtqs)
to send and receive data between the virtio-net driver and the virtual or
physical backed. The VirtIO standard originally defined a single type of virtq
called split-ring queue. The latest edition of the standard (v1.1) adds a
different type of the virtq, called packed-ring queue. A different layout of
queue elements allows to increase the performance in both virtual and physical
backeds.&lt;/p&gt;
&lt;p&gt;Split-ring support is the default option in VirtIO. Backends supporting
the packed-ring virtqs advertise this by setting the &lt;cite&gt;VIRTIO_F_RING_PACKED&lt;/cite&gt;
feature bit during the feature negotiation. A guest driver then chooses the
virtq layout based on what it supports. As both options are identical features
wise, and the packed-ring is more efficient, the latter is typically chosen.&lt;/p&gt;
&lt;p&gt;QEMU added support for the packed virtqs in v4.2 and LibVirt in v6.3. Qemu and
LibVirt supports the packed-ring virtqs via the &lt;cite&gt;packed&lt;/cite&gt; option. However, note
that this option &lt;em&gt;does not&lt;/em&gt; force the VM to use the packed-ring virtq. It acts
as a mask, allowing the backed to advertise the support when set. The driver in
the VM is still responsible for choosing the layout of virtqs.&lt;/p&gt;
&lt;p&gt;This blueprint proposes to add a Nova flavor extra_spec and Glance image
property, that sets the &lt;cite&gt;packed&lt;/cite&gt; option to &lt;cite&gt;true&lt;/cite&gt; on the node. This way all VMs
running on the node are allowed to choose the virtq layout based on what is
offered by the backed, rather than being froced to use split-ring.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to benefit from the increase in the virtio-net
performance, by using a more efficient virtq structure.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_virtio_packed_ring&lt;/span&gt;&lt;/code&gt; for image property and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:virtio_packed_ring&lt;/span&gt;&lt;/code&gt; for flavor extra specs.
Users will control the packed virtqueue feature, and be able to disable
it if desired.&lt;/p&gt;
&lt;p&gt;hw_virtio_packed_ring=true|false  (default false)
hw:virtio_packed_ring=true|false  (default false)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide new compute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_NET_VIRTIO_PACKED&lt;/span&gt;&lt;/code&gt; capablity trait.
This trait can be required/forbidden by user. Nova-compute agent
will automatically set this trait to the resource provider summary
as far as current minimal libvirt support version by OpenStack is higher
than feature required version 6.3.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This spec will update scheduling process. ALL_REQUEST_FILTERS will be
extended with new filter packed_virtqueue_filter. It will update RequestSpec
with new trait in case if image property or flavor extra_spec is enabled to
avoid migration to the node without packed virtqueue feature support.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Leave as-is, operator will not have additional performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;VMs using virtio-net will see an increase in performance. The increase can be
anywhere between 10/20% (see DPDK Intel Vhost/virtio perf. reports) and 75%
(using Napatech SmartNICs).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;If operators upgrade their computes one by one, only new upgraded computes will
support that feature for a while.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;justas_napa on IRC and Gerrit&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Additional assignees:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dvo-plv on IRC and Gerrit&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Sean Mooney (sean-k-mooney)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add image property and flavor extra specs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide new compute capability trait&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update scheduling process&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;New Unit and Functional tests will be added:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Verify image property and flavor extra spec options for correct
configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify nodes filtering by trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify correct Libvirt xml with driver packet option configuration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Configuration options reference will require an update.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;VirtIO standard:
&lt;a class="reference external" href="https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html"&gt;https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LibVirt Domain XML reference
&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#virtio-related-options"&gt;https://libvirt.org/formatdomain.html#virtio-related-options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 13 Mar 2024 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id8" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id8" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id8" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backing_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret for the backing file associated with the
disk in the case of qcow2.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store raw keys in the key manager due to their
support of the dm-crypt &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format. With &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; it is not
necessary to store raw keys as it does not directly encrypt data with the
provided key &lt;a class="reference external" href="https://www.man7.org/linux/man-pages/man8/cryptsetup.8.html#NOTES"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID(s).&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypt these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id9" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id8" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; imagebackend, both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]images_type&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt;
&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]use_cow_images&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; must be configured in order for
resize to work. This is also true without encryption but it may still be
helpful to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that a user must have policy permission to create secrets in
Barbican in order for encryption to work for that user. Secrets are created
in Barbican using the user’s auth token. Admins have permission to create
secrets in Barbican by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/ephemeral-storage-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/ephemeral-storage-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id10"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 05 Mar 2024 00:00:00 </pubDate></item><item><title>Flavor and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will only cover the high level changes to the API and compute
layers, implementation within specific virt drivers is left for separate
specs.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image, or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used. For this, a configuration option will be
used to provide a default format per compute which will initially default to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; with no other choices at this time.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To enable snapshot and shelve of instances using ephemeral encryption, the UUID
of the encryption secret and the encryption format for the resultant image will
be kept with the image using the standardized Glance image properties &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/915726"&gt;[1]&lt;/a&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The secret UUID and encryption format are needed when creating an instance from
an ephemeral encrypted snapshot or when unshelving an ephemeral encrypted
instance.&lt;/p&gt;
&lt;p&gt;The other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt*&lt;/span&gt;&lt;/code&gt; Glance image properties will also be set at the time
of snapshot:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_cipher&lt;/span&gt;&lt;/code&gt; - the cipher algorithm, e.g. ‘AES256’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_deletion_policy&lt;/span&gt;&lt;/code&gt; - on image deletion indicates whether the
key should be deleted too&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_decrypt_container_format&lt;/span&gt;&lt;/code&gt; - format change, e.g. from ‘compressed’ to
‘bare’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_decrypt_size&lt;/span&gt;&lt;/code&gt; - size after payload decryption&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="possible-future-work"&gt;
&lt;h4&gt;Possible future work&lt;/h4&gt;
&lt;p&gt;In the future, we could consider supporting a cloud with a mix of compute hosts
providing either LUKSv1 (qcow2|raw|rbd) or legacy dm-crypt PLAIN (LVM)
encryption formats.&lt;/p&gt;
&lt;p&gt;The encryption format used would be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and would be used to schedule to a compute host which supports the specified
format.&lt;/p&gt;
&lt;p&gt;The format would be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;legacy_dmcrypt_plain&lt;/span&gt;&lt;/code&gt; for the dm-crypt PLAIN format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and if neither are specified, the format would be taken from the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_format&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/915726"&gt;[1]&lt;/a&gt; if the source image is encrypted. If the
source image is not encrypted, the format would be taken from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; after an instance lands on a
compute host.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="management-of-secret-data-with-the-key-manager-service"&gt;
&lt;h3&gt;Management of secret data with the Key Manager service&lt;/h3&gt;
&lt;p&gt;The passphrases of encrypted disks are managed using a Key Manager service such
as &lt;a class="reference external" href="https://docs.openstack.org/barbican/latest/index.html"&gt;Barbican&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nova will create, retrieve, and delete disk passphrases using the authorization
token of the user calling Nova API. The cloud operator must consider the
implications of secret ownership with regard to server actions and who is
allowed to perform them:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;  ┌─────────────────────┐                        ┌────────────────────┐
  │                     │                        │                    │
  │                     │                        │                    │
  │       Nova API      │◄───────────────────────┤    Barbican API    │
  │                     │                        │                    │
  │                     ├─────┬────────────┬────►│                    │
  │                     │     │ User token │     │                    │
  │                     │     └────────────┘     │                    │
  │                     │                        │                    │
  └──────────▲──────────┘                        └────────────────────┘
             │
             │
             │
             │
             │
┌────────────┤
│ User token │
└────────────┤
             │
             │
             │
             │
        ┌─────────┐
        │         │
        │  User   │
        │         │
        └─────────┘
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default, Barbican scopes the ownership of a secret at the project level.
This means that many calls in the Barbican API will perform an additional check
to ensure that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; of the token matches the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;
stored as the secret owner. Users who are members of the same project have
access to each other’s secrets in this configuration.&lt;/p&gt;
&lt;p&gt;For admin-only APIs such as cold migrate, live migrate, and evacuate, the
user calling Nova API to perform these server actions needs both:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Access the Barbican secrets of the owner of the server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; role in order to call admin-only Nova APIs such as cold
migration, live migration, evacuate, etc&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In a default Barbican configuration, secret ownership will be scoped to the
project which created it, so in such an environment a user would need to be a
&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/admin/service-api-protection.html#project-administrators"&gt;project administrator&lt;/a&gt; or any user who has both project membership and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; role.&lt;/p&gt;
&lt;p&gt;Note that it is possible for cloud operators to implement more fine-grained
control of secrets in Barbican using &lt;a class="reference external" href="https://docs.openstack.org/barbican/latest/admin/access_control.html"&gt;access control lists&lt;/a&gt;. Secrets could be
made to be scoped at the user level, for example, instead of at the project
level. In such a configuration, a &lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/admin/service-api-protection.html#project-administrators"&gt;project administrator&lt;/a&gt;,  would &lt;strong&gt;not&lt;/strong&gt; be
allowed perform admin-only API server actions on a server belonging to a
different user in the project.&lt;/p&gt;
&lt;p&gt;Operators must plan ahead to determine what configuration and access control of
Barbican secrets they need in their environments.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;For legacy deployments using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[oslo_policy]enforce_scope&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; in their
service configuration files, an additional step is required to allow
users to create servers with encrypted local disks.&lt;/p&gt;
&lt;p&gt;In a legacy deployment, users must have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;creator&lt;/span&gt;&lt;/code&gt; role or the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; role assigned to them in Keystone in order to be allowed to
create secrets in the Barbican key manager service. Otherwise, user requests
to create servers with encrypted local disks will fail.&lt;/p&gt;
&lt;div class="highlight-console notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;role&lt;span class="w"&gt; &lt;/span&gt;list
&lt;span class="go"&gt;+----------------------------------+---------------------------+&lt;/span&gt;
&lt;span class="go"&gt;| ID                               | Name                      |&lt;/span&gt;
&lt;span class="go"&gt;+----------------------------------+---------------------------+&lt;/span&gt;
&lt;span class="go"&gt;| 068b4910f0eb4a1cb6a4a2a1e94c3dfe | reader                    |&lt;/span&gt;
&lt;span class="go"&gt;| 25dc4ed8f3814fd1941a580d78f2b635 | service                   |&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;| 7e832eeb2c2842c9b03c376bf3113247 | creator                   |&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;| 59df386beb0f460095b7622fc1a45e22 | member                    |&lt;/span&gt;
&lt;span class="go"&gt;| 655bbf1b9f844399bcfbfbbef4248045 | admin                     |&lt;/span&gt;
&lt;span class="go"&gt;+----------------------------------+---------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="create-a-new-key-manager-secret-for-each-block-device-mapping"&gt;
&lt;h3&gt;Create a new key manager secret for each block device mapping&lt;/h3&gt;
&lt;p&gt;The approach for disk image secrets is that each disk image has a unique
secret.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;Let’s say &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt; &lt;span class="pre"&gt;A&lt;/span&gt;&lt;/code&gt; has 3 disks: one root disk, one ephemeral disk, and
one swap disk. Each disk will have its own secret.&lt;/p&gt;
&lt;p&gt;With qcow2, if an instance is created from an encrypted source image, the
resulting backing file will have the same passphrase as the source image in
order for the backing file to be shared among multiple instances. For each
instance sharing the backing file, the instance has its own “copy” of the
secret (a new Barbican secret that has the same passphrase).&lt;/p&gt;
&lt;p&gt;This prevents a single point of failure with regard to Barbican secret
deletion. For example, if 100 instances share the same encrypted backing file
and a user mistakenly deletes a Barbican secret for the backing file, only one
instance or image will be affected. If one Barbican secret were shared by the
100 instances using the same encrypted backing file, 100 instances and the
source image would be affected.&lt;/p&gt;
&lt;p&gt;Barbican does have a reference counting API for secret consumers which
increments and decrements an internal counter over HTTP. If the count for a
given secret becomes incorrectly zero for any reason, over time, (race
conditions, etc), the API will allow deletion of that secret even if it is in
use.&lt;/p&gt;
&lt;p&gt;This table is intended to illustrate the way secrets are handled in various
scenarios.&lt;/p&gt;
&lt;table class="docutils align-left"&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Instance or Image&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Disk&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Secret
(passphrase)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Notes&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td rowspan="3"&gt;&lt;p&gt;Instance A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 1&lt;/p&gt;&lt;/td&gt;
&lt;td rowspan="3"&gt;&lt;p&gt;Secret 1, 2, and 3 will be automatically deleted
by Nova when Instance A is deleted and its disks are
destroyed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;disk.eph0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;disk.swap&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Image Z (snapshot)
created from
Instance A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 4
(copy of Secret 1 by default)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 4 will &lt;strong&gt;not&lt;/strong&gt; be automatically deleted and
manual deletion will be needed if/when Image Z is
deleted from Glance&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td rowspan="4"&gt;&lt;p&gt;Instance B
created from
Image Z (snapshot)&lt;/p&gt;&lt;/td&gt;
&lt;td rowspan="2"&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 5 &lt;sup&gt;*&lt;/sup&gt; (copy of Secret 4)&lt;/p&gt;&lt;/td&gt;
&lt;td rowspan="4"&gt;&lt;p&gt;Secret 5, 6, 7, and 8 will be automatically deleted
by Nova when Instance B is deleted and its disks are
destroyed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Secret 6&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;disk.eph0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 7&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;disk.swap&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 8&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td rowspan="3"&gt;&lt;p&gt;Instance C&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 9&lt;/p&gt;&lt;/td&gt;
&lt;td rowspan="3"&gt;&lt;p&gt;Secret 9, 10, and 11 will be automatically deleted
by Nova when Instance C is deleted and its disks are
destroyed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;disk.eph0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 10&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;disk.swap&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 11&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Image Y (snapshot)
created by shelve
of Instance C&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 9&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret 9 is &lt;strong&gt;reused&lt;/strong&gt; when Instance C is shelved
in part to prevent the possibility of a change in
ownership of the root disk secret if, for example,
an admin user shelves a non-admin user’s instance.
This approach could be avoided if there is some way
we could create a new secret using the instance’s
user/project rather than the shelver’s user/project&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rescue disk
created by rescue
of Instance A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;None&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A rescue disk is only encrypted if an encrypted
rescue image was specified.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Rescue disk
created by rescue
of Instance A
using encrypted
rescue image&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;disk (root)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Secret of encrypted rescue image&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The secret of the encrypted rescue image will be
reused and no new secrets will be created or deleted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; backing file secret for qcow2 only&lt;/p&gt;
&lt;/section&gt;
&lt;section id="encrypted-source-images"&gt;
&lt;h3&gt;Encrypted source images&lt;/h3&gt;
&lt;p&gt;The default behavior when creating an instance from an encrypted source image
will be to create encrypted disks. The reasoning is that we aim to avoid
“surprise” decryption of images and that decryption should be something that a
user or flavor or image has to opt-in to and explicitly request so the intent
is clear.&lt;/p&gt;
&lt;p&gt;Encrypted source images will have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_id&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_format&lt;/span&gt;&lt;/code&gt;, and other &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/915726"&gt;[1]&lt;/a&gt; image properties in their image
metadata.  Access to the secret of the encrypted source image is determined by
the key manager API policy and/or access control lists.&lt;/p&gt;
&lt;p&gt;At this time, we expect to use a subset of the standardized image properties:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_format&lt;/span&gt;&lt;/code&gt; - to know how to interpret the image format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_id&lt;/span&gt;&lt;/code&gt; - to copy/convert/etc the source image if needed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;When creating an instance with encrypted disks from an encrypted source image
when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; has not been set, we will either use the
presence of the automatically stored &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_os_encrypt_key_id&lt;/span&gt;&lt;/code&gt; in system
metadata or potentially store &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_hw_ephemeral_encryption=true&lt;/span&gt;&lt;/code&gt; in the
instance system metadata and use it to ensure an instance will be scheduled to
a compute host which supports ephemeral encryption.&lt;/p&gt;
&lt;p&gt;If the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_id&lt;/span&gt;&lt;/code&gt; image property is set on the encrypted image and
the image or flavor also has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption=false&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption=false&lt;/span&gt;&lt;/code&gt; explicitly set, we will reject the API
request with a 409 conflict error at this time.&lt;/p&gt;
&lt;p&gt;We could consider future work to interpret the aforementioned combination of
image property settings as an intentional request to create an instance with
unencrypted disks from the encrypted source image and perform the decryption.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="encrypted-backing-files-qcow2"&gt;
&lt;h3&gt;Encrypted backing files (qcow2)&lt;/h3&gt;
&lt;p&gt;The approach regarding backing files is that they will be encrypted if the
source image from which it was created is encrypted. If the source image from
which the disk is created is not encrypted, the backing file stored internally
in Nova will also not be encrypted. If the source image is encrypted, the
backing file will also be encrypted.&lt;/p&gt;
&lt;p&gt;An encrypted backing file uses the same passphrase as the source image from
which it was created. This is required for the encrypted backing file to be
shared among multiple instances in the same project.&lt;/p&gt;
&lt;p&gt;Backing files for ephemeral disks and swap disks are never encrypted as they
are always created from blank disks.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="snapshots-of-instances-with-ephemeral-encryption"&gt;
&lt;h3&gt;Snapshots of instances with ephemeral encryption&lt;/h3&gt;
&lt;p&gt;When an instance with ephemeral encryption is snapshotted, the behavior for
encrypting the image snapshot is determined by request parameters which will
be added to the snapshot API.&lt;/p&gt;
&lt;p&gt;The API request parameters are intended to support workflows that involve
sharing of encrypted image snapshots with other projects or users.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An instance owner wants to back up their disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An instance owner wants to make a copy of their disk that is encrypted with
a new key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An instance owner wants to make a copy of their disk using an existing key
that belongs to a different project or user (provided that project or user
has created the necessary &lt;a class="reference external" href="https://docs.openstack.org/barbican/latest/admin/access_control.html"&gt;access control list&lt;/a&gt; for the secret)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An instance owner wants to create an unencrypted public copy of their disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An instance owner with an unencrypted disk wants to make an encrypted copy to
facilitate secure exfiltration of their disk to another location&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="new-api-microversion-for-create-image-createimage-action"&gt;
&lt;h4&gt;New API microversion for Create Image (createImage Action)&lt;/h4&gt;
&lt;p&gt;A new microversion will be added to the &lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/#create-image-createimage-action"&gt;create image API&lt;/a&gt; to support
ephemeral encryption options. Users will be able to choose how they want
encryption of the new image snapshot to be handled. They can use the same key
as the image being snapshotted (the default), have Nova generate a new key
and use it to encrypt the image snapshot, provide their own key secret UUID
to use to encrypt the image snapshot, or not encrypt the image snapshot at
all.&lt;/p&gt;
&lt;section id="request-for-post-servers-server-id-action-with-createimage"&gt;
&lt;h5&gt;Request for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createImage&lt;/span&gt;&lt;/code&gt;&lt;/h5&gt;
&lt;table class="docutils align-left" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Request&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 20.0%"/&gt;
&lt;col style="width: 5.0%"/&gt;
&lt;col style="width: 5.0%"/&gt;
&lt;col style="width: 70.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;In&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;server_id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;path&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;string&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The UUID of the server.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;createImage&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;object&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The action to create a snapshot of the image or the volume(s) of the
server.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;string&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The display name of an Image.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;metadata (Optional)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;object&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Metadata key and value pairs for the image. The maximum size for each
metadata key and value pair is 255 bytes.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;encryption (Optional)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;object&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Encryption options for the image to create. These options apply only to
encrypted local disks.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;encryption.key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;string&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The key to use to encrypt the image snapshot. Valid values are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;same&lt;/span&gt;&lt;/code&gt;: Use the same key to encrypt the image snapshot.
This is the default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new&lt;/span&gt;&lt;/code&gt;: Generate a new key and use it to encrypt the image snapshot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;existing&lt;/span&gt;&lt;/code&gt;: The user will provide the UUID of an existing secret in
the key manager service to use to encrypt the image snapshot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt;: Do not encrypt the image snapshot.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;encryption.secret_uuid (Optional)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;string&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The UUID of the key manager service secret that was used to encrypt the
image snapshot.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"createImage"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo-image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"meta_var"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"meta_val"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"encryption"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"same|new|existing|none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"secret_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;secret uuid&amp;gt; if 'key' is 'existing', or absent"&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Request choices for encryption.key:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;same&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Use the same key to encrypt the new disk image. This is the default.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Generate a new key to encrypt the new disk image.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;existing&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Use the provided &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;secret&lt;/span&gt; &lt;span class="pre"&gt;uuid&amp;gt;&lt;/span&gt;&lt;/code&gt; to encrypt the new disk image.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Do not encrypt the new disk image.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Ceph release Quincy (v17) and older do not support creating a cloned image
with an encryption key different from its parent. For this reason, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption.key&lt;/span&gt;&lt;/code&gt; request parameter with a value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new&lt;/span&gt;&lt;/code&gt; will not be
supported with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd&lt;/span&gt;&lt;/code&gt; image backend for those versions of Ceph.&lt;/p&gt;
&lt;p&gt;The plan if a user requests a snapshot with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption.key&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new&lt;/span&gt;&lt;/code&gt;
and Ceph &amp;lt;= Quincy (v17), the snapshot server action will be marked as
failed with a message that explains that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new&lt;/span&gt;&lt;/code&gt; is not supported in the
deployment.&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://github.com/ceph/ceph/commit/1d3de19"&gt;https://github.com/ceph/ceph/commit/1d3de19&lt;/a&gt; for reference.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="response-for-post-servers-server-id-action-with-createimage"&gt;
&lt;h5&gt;Response for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createImage&lt;/span&gt;&lt;/code&gt;&lt;/h5&gt;
&lt;p&gt;(There will be no change to the response parameters.)&lt;/p&gt;
&lt;table class="docutils align-left" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Response&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 20.0%"/&gt;
&lt;col style="width: 5.0%"/&gt;
&lt;col style="width: 5.0%"/&gt;
&lt;col style="width: 70.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;In&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;image_id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;body&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;string&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The UUID for the resulting image snapshot.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0e7761dd-ee98-41f0-ba35-05994e446431"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="create-server-back-up-createbackup-action-api"&gt;
&lt;h4&gt;Create Server Back Up (createBackup Action) API&lt;/h4&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; API with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createBackup&lt;/span&gt;&lt;/code&gt; will not be
changed. Image snapshots created by this API will be encrypted using the same
key.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="image-metadata-for-image-snapshots-of-encrypted-disks"&gt;
&lt;h4&gt;Image metadata for image snapshots of encrypted disks&lt;/h4&gt;
&lt;p&gt;When an encrypted image snapshot is created, its image properties will be set
to contain encryption information when Nova uploads it to Glance. There is a
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/915726"&gt;Glance spec&lt;/a&gt; proposed to establish a set of standardized image properties for
all projects to use when working with encrypted Glance images:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_format&lt;/span&gt;&lt;/code&gt; - the main mechanism used, e.g. ‘LUKS’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_cipher&lt;/span&gt;&lt;/code&gt; - the cipher algorithm, e.g. ‘AES256’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_id&lt;/span&gt;&lt;/code&gt; - reference to key in the key manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_key_deletion_policy&lt;/span&gt;&lt;/code&gt; - on image deletion indicates whether&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;the key should be deleted too&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_decrypt_container_format&lt;/span&gt;&lt;/code&gt; - format after payload decryption, e.g.&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;‘qcow’&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_decrypt_size&lt;/span&gt;&lt;/code&gt; - size after payload decryption&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;and will be used for snapshots of encrypted images in Nova.&lt;/p&gt;
&lt;p&gt;When a new instance is created from an encrypted image, the image properties
are passed down to the lower layers by their presence in the instance’s system
metadata with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_&lt;/span&gt;&lt;/code&gt; prefix. The system metadata is used because at the
lower layers (where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;convert&lt;/span&gt;&lt;/code&gt; is called, for example) we no longer
have access to the image metadata and nontrivial refactoring to pass image
metadata to several lower layer methods, or similar, would be required
otherwise.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="snapshots-created-by-shelving-instances-with-ephemeral-encryption"&gt;
&lt;h3&gt;Snapshots created by shelving instances with ephemeral encryption&lt;/h3&gt;
&lt;p&gt;When an instance with ephemeral encryption is shelved, the existing root disk
encryption secret is &lt;strong&gt;reused&lt;/strong&gt; and will be used to unshelve the instance
later. This is done to prevent a potential change in ownership of the root disk
encryption secret in a scenario where an admin user shelves a non-admin user’s
instance, for example. If a new secret were created owned by the admin user,
the non-admin user who owns the instance would be unable to unshelve the
instance.&lt;/p&gt;
&lt;p&gt;This behavior could be avoided however if there is some way we could create a
new encryption secret using the instance’s user and project rather than the
shelver’s user and project. If that were possible, we would not need to reuse
the encryption secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rescue-disk-images-created-when-the-rescue-image-is-encrypted"&gt;
&lt;h3&gt;Rescue disk images created when the rescue image is encrypted&lt;/h3&gt;
&lt;p&gt;When rescuing an instance and an encrypted rescue image is specified, the
rescue image secret UUID from the image property will be used to encrypt the
rescue disk. A new key manager secret will not be created.&lt;/p&gt;
&lt;p&gt;The rescue image secret is used because it will exist whether the instance has
an encrypted root disk or not. It is technically possible to specify an
encrypted rescue image for an instance that does not otherwise have encrypted
local disks.&lt;/p&gt;
&lt;p&gt;The rescue disk will be encrypted if and only if the rescue image is encrypted,
with the objective of not creating unencrypted data at rest from data that is
currently encrypted at rest.&lt;/p&gt;
&lt;p&gt;The new virt driver secret will be created for the rescue disk and is deleted
when the instance is unrescued.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="cleanup-of-ephemeral-encryption-secrets"&gt;
&lt;h3&gt;Cleanup of ephemeral encryption secrets&lt;/h3&gt;
&lt;p&gt;Ephemeral encryption secrets are deleted from the key manager and the virt
driver when the corresponding instance is deleted and its disks are destroyed.&lt;/p&gt;
&lt;p&gt;Virt driver secrets may be created on destination hosts and deleted from source
hosts as needed during instance migrations.&lt;/p&gt;
&lt;p&gt;Key manager secrets are however &lt;strong&gt;only&lt;/strong&gt; deleted when the disks associated with
them are destroyed.&lt;/p&gt;
&lt;p&gt;Encryption secrets that are created when a snapshot is created are &lt;strong&gt;never&lt;/strong&gt;
deleted by Nova. It would only be acceptable to delete the secret if and when
the image snapshot is deleted from Glance. There is a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_encrypt_deletion_policy&lt;/span&gt;&lt;/code&gt; image property proposed in the standardized
Glance image properties that Nova will set to tell Glance to go ahead and
delete the key manager secret for the image at the same time the image is
deleted.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backing_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;This will contain the UUID of the associated encryption secret for the
backing file for the disk in the case of qcow2.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; field may be used to store the encryption
parameters that were used to create the disk such as cipher algorithm,
cipher mode, and initialization vector generator algorithm.&lt;/p&gt;
&lt;p&gt;The intention will be to be able to track the encryption attributes of each
disk to aid in handling future upgrade scenarios such as removal of an
algorithm or a change in a default in QEMU.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility trait was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-values"&gt;
&lt;h3&gt;Block resize between flavors with different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; values&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;p&gt;Support for resizing between flavors with different ephemeral encryption
parameters is planned to be added in a separate patch later in the series.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;legacy_dmcrypt_plain&lt;/span&gt;&lt;/code&gt;
encryption format and configured options on the host before clearing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new API microversion will be created to add encryption options to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createImage&lt;/span&gt;&lt;/code&gt; server action API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed by the user who owns the instance. Requests to
rebuild between images that differ in their ephemeral encryption options will
be rejected. This is to prevent a change in the ownership of secrets for the
instance disks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more image backends such as qcow2 and rbd.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users may be able to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavor.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backing_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/915726"&gt;https://review.opendev.org/c/openstack/glance-specs/+/915726&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-left" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 05 Mar 2024 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.2/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.2 Dalmatian&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 19 Jan 2024 00:00:00 </pubDate></item><item><title>PCI Passthrough Groups</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/approved/pci-passthrough-groups.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pci-passthrough-groups"&gt;https://blueprints.launchpad.net/nova/+spec/pci-passthrough-groups&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec allows operators to create a flavor using a PCI alias to
request a group of PCI devices. These groups of PCI devices are tracked
as a single indivisible unit within Placement. The default custom
resource class used to track these PCI groups is derived from the
PCI group type name, and the name of the inventory is derived from
the PCI group name. The pci_alias config already supports mapping
to a specific placement resource class.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Some PCI devices only make sense to be consumed as a group.
When you assign the grouped PCI devices to a VM, all of the
devices in the group as always consumed together by a single VM.
Currently Nova does not understand any grouping other than
NUMA affinity.&lt;/p&gt;
&lt;p&gt;While there are some cases where a device could be consumed by
multiple different groups, that are dynamically picked based on
demand, we are ignoring these use cases for now.
In particular, we make the simplifying restriction
that a tracked PCI device can only be a member of a single group,
and when a PCI device is a member of a group, it can only be used
as part of that PCI group.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Some GPUs expose both a graphics physical function and an audio
function. In order to support passing through both devices, we need
to ensure that we pass through a matching pair of devices.
This spec would allow a device group to be created such that
operators configure the matching pairs of audio and graphics
devices, and users can request one (or more) of those pairs via
the usual PCI alias.&lt;/p&gt;
&lt;p&gt;Note, we are currently excluding the use case of users requesting
either the pair of devices or just the graphics device, as that
would result in additional complexity that should be considered
in a separate follow on specification.&lt;/p&gt;
&lt;p&gt;Let us consider the specific case of the Graphcore C200 device,
where a set of PCI cards are connected together via IPU-Link:
&lt;a class="reference external" href="https://docs.graphcore.ai/projects/C600-datasheet/en/latest/product-description.html#ipu-link-cables"&gt;https://docs.graphcore.ai/projects/C600-datasheet/en/latest/product-description.html#ipu-link-cables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each physical card presents two PCI devices. The card can be used
independently of other cards if a matched pair of devices are
presented to the VM. PCI groups allows this device to be correctly
passed through to VMs by ensuring a matched pair of PCI devices are
always assigned to each VM.&lt;/p&gt;
&lt;p&gt;In addition, some servers can be statically configured to group
either two devices, four devices or eight devices as a single group.
These can all be statically configured using PCI group to ensure
we always respect the non-PCI connectivity between those PCI devices.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The key parts of this change include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;extend &lt;cite&gt;[pci]device_spec&lt;/cite&gt; to model groups of PCI devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;devices are linked by both a group type name, and a specific group name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the group type name is used to generate a custom resource class,
i.e. &lt;cite&gt;CUSTOM_PCI_GROUP&amp;lt;group_type_name&amp;gt;&lt;/cite&gt;. Note this is just the default
that changes when you specify a group type name, and it can be
overrriden by explicitly specifying a different resource_class tag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each group is registered in placement, in a similar way to a device.
Each group being a separate resource provider with a single inventory
item for the associated group type custom resource type, with a name
that is generated from the group_name rather than the PCI device address&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extend &lt;cite&gt;[pci]alias&lt;/cite&gt; simply mapps to the resource class mentioned
above, such as &lt;cite&gt;CUSTOM_PCI_GROUP_&amp;lt;group_type_name&amp;gt;&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PCI tracker will have the group_name and group_type_name added to
each device that is being tracked, such that we can look up a group
of devices associated with each specific named group tracked
in placement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There will be configuration validation checks:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pci groups are only supported when PCI devices are tracked in placement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all device groups must have two or more PCI devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;each physical PCI device can only be in one group,
and must only be tracked in placement once&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, lets consider the following PCI devices:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;4e:00.0 Processing accelerators: Graphcore Ltd Device 0003&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;4f:00.0 Processing accelerators: Graphcore Ltd Device 0003&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;89:00.0 Processing accelerators: Graphcore Ltd Device 0003&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;8a:00.0 Processing accelerators: Graphcore Ltd Device 0003&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The two physical cards, spread across two NUMA nodes can be presented
in two possible ways: either two groups or a single group, depending on
the use cases. For example, two separate devices would be::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4e:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4f:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4e:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4f:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource_class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_PCI_GROUP_C200_X1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;But exposing the two cards, exposed as four PCI devices,
as a single unit of 4 PCI devices, would look like this::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4e:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4f:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4e:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;device_spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;":4f:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"graphcore_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"c200_x2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource_class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_PCI_GROUP_C200_X2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;For some simple cases, NUMA affinity can simulate what is required.
But currently hardware like Graphcore C200 does not work well with Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;PCI tracker needs to be extended to include group_name and group_type
for each PCI device.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;No impact&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;No impact&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;No impact&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;No impact&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No impact&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The device spec configuration gets some extra options to help
define groups, and the default resource class changes when you
use the new device_group tags, as discussed above.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Devices that are exposed as a group must be not currently
tracked in placement when starting to expose them as a group.&lt;/p&gt;
&lt;p&gt;Once new compute nodes will report the new resoruce classes,
which should naturally gate the need for older compute nodes
to know what to do with the new PCI device configuration.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johngarbutt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nathanharper&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gibi?&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update pci device config to support pci groups&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update PCI device tracker to know about pci groups&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach groups of devices when device alias requests
a resource class that maps to a PCI device group&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update placement with the avilable resources
from the described pci groups&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add a functional test, similar to vgpu tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Configuration changes need to be documented correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 31 Oct 2023 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/approved/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result operators need to ensure that Manila
backend storage is routable from the guest subnets.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not
be covered by this spec, any requests to shelve, evacuate, resize, cold migrate
or live migrate an instance with a share attached will be rejected with a
HTTP409 response for the time being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
once &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;support lands in libvirt itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.
(ref: &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user documentation&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Two new compute capability traits and filters will be introduced to model an
individual compute’s support for virtio-fs and file backed memory.
And while associating a share to an instance, a check will ensure the host
running the instance will support the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and either the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;that the instance is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;From an operator’s point of view, it means
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; support requires that
operators must upgrade all their compute nodes to the version supporting
shares using virtiofs.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; support requires that operators configure one or
more hosts with file backed memory. Ensuring the instance will land on one of
these hosts can be achieved by creating an AZ englobing these hosts.
And then instruct users to deploy their instances in this AZ.
Alternatively, operators can guide the scheduler to choose a suitable host
by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_MEM_BACKING_FILE=required&lt;/span&gt;&lt;/code&gt; as an extra spec or
image property.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the users with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;p&gt;Share mapping status:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                     &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;   &lt;span class="n"&gt;Reboot&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
    &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;--------------+&lt;/span&gt;
    &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;mounted&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;active&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;umount&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;error&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+-------------+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="n"&gt;φ&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Attach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;unmounted&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="n"&gt;v&lt;/span&gt;                                 &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+--------------&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;inactive&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;φ&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means no entry in the database. No association between a share and a server.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Attach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means POST /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Detach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means DELETE /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This chart describe the share mapping status (nova), this is independent from
the status of the Manila share.&lt;/p&gt;
&lt;p&gt;Share attachment/detachment can only be done if the VM state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;.
These are operations only on the database, and no RPC calls will be required
to the compute API. This is an intentional design for this spec.
As a result, this could lead to situation where the VM start operation fails
as an underlying share attach fails.&lt;/p&gt;
&lt;p&gt;Mount operation will be done when the share is not mounted on the compute host.
If a previous share would have been mounted on the compute host for another
server, then it will attempt to mount it and a warning will be logged that
the share was already mounted.&lt;/p&gt;
&lt;p&gt;Umount operation will be really done when the share is mounted and not used
anymore by another server.&lt;/p&gt;
&lt;p&gt;With the above mount and umount operation, the state is stored in memory and
do not require a lookup in the database.&lt;/p&gt;
&lt;p&gt;The share will be mounted on the compute host using read/write mode.
Read-only will not be supported as a share could not be mounted read-only
and read/write at the same time. If the user wants to mount the share
read-only, it will have to do it in the VM fstab.&lt;/p&gt;
&lt;p&gt;Manila share removal issue:&lt;/p&gt;
&lt;p&gt;Despite a share being used by instances, it can be removed by the user.
As a result, the instances will lose access to the data and might cause
difficulties in removing the missing share and fixing the instance.
This is an identified issue that requires Manila modifications.
A solution was identified with the Manila team to attach metadata to the share
access-allow policy that will lock the share and prevent its deletion until
the lock is not removed.
If the above Manila change can land in the Zed cycle,
the proposal here is to use the lock mechanism in Nova.
Otherwise, clearly document the known issue as unsupported and warn users that
they should take care and avoid this pitfall.&lt;/p&gt;
&lt;p&gt;Instance metadata:&lt;/p&gt;
&lt;p&gt;Add instace shares in the instance metadata.
Extend DeviceMetadata with ShareMetadata object containing &lt;cite&gt;shareId&lt;/cite&gt; and
&lt;cite&gt;tag&lt;/cite&gt; used to mount the virtiofs on an instance by the user.
See &lt;a class="reference internal" href="#caracal-other-end-user-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PROJECT_ADMIN will be able to see details of the attachment id and export
location stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance should have the required capabilities to enable
virtiofs (see above).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a synchronous API. As a result, the VM share attachement state
is defined in the database and set as inactive.
Then, power on the VM will do the required operations to attach the share and
set it as active if there are no errors.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter in the request body, when not
provided it will be the shareId(UUID) as always provided in the request.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; if povided by the user must be an ASCII string with a maximum
lenght of 64 bytes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Primary key autoincrement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inactive&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within
the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the
underlying host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_proto&lt;/span&gt;&lt;/code&gt; - The Shared File Systems protocol (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NFS&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CEPHFS&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;The database field &lt;cite&gt;status&lt;/cite&gt; and &lt;cite&gt;share_proto&lt;/cite&gt; values will not be enforced
using enums allowing future changes and avoid database migrations.
However, to make code more robust, enums will be defined on the object fields.&lt;/p&gt;
&lt;p&gt;Fields containing text will use String and not Text type in the database schema
to limit the column width and be stored inline in the database.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to mount the
share to the host and the host filesystem location should
not be logged by Nova and only accessible by default through the API by admins.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One to add new notifications for share attach and share detach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One to extend the instance update notification with the share mapping
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Share mapping in the instance payload will be optional and controlled via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include_share_mapping&lt;/span&gt;&lt;/code&gt; notification configuration parameter. It will be
disabled by default.&lt;/p&gt;
&lt;p&gt;Proposed payload for attached and detached notification will be the same as
the one returned by the show command with admin rights.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Proposed instance payload for instance updade, will be the list of share
attached to this instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-ffffffffffff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7987"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server2.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="caracal-other-end-user-impact"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Users could use the instance metadata to discover and auto mount the share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.
While there will be near local performance between the vm and host,
the actual performance will be limited by the network performance of
the network file share protocol and hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and capability traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (initial contributor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new capability traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 16 Oct 2023 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store a symmetric key in the key manager. This
remains a long running piece of technical debt in the encrypted volume
implementation as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; does not directly encrypt data with the provided
key.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID.&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypt these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; imagebackend, both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]images_type&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt;
&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]use_cow_images&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; must be configured in order for
resize to work. This is also true without encryption but it may still be
helpful to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that a user must have policy permission to create secrets in
Barbican in order for encryption to work for that user. Secrets are created
in Barbican using the user’s auth token. Admins have permission to create
secrets in Barbican by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ephemeral-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ephemeral-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 05 Oct 2023 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will only cover the high level changes to the API and compute
layers, implementation within specific virt drivers is left for separate
specs.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To enable snapshot and shelve of instances using ephemeral encryption, the UUID
of the encryption secret is stored in the key manager for the resultant image
will be kept with the image as an image property:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The secret UUID is needed when creating an instance from an ephemeral encrypted
snapshot or when unshelving an ephemeral encrypted instance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="create-a-new-key-manager-secret-for-every-new-encrypted-disk-image"&gt;
&lt;h3&gt;Create a new key manager secret for every new encrypted disk image&lt;/h3&gt;
&lt;p&gt;The approach for disk image secrets is to never share secrets between different
disk images and that each disk image has a unique secret. This is done to
address both 1) the security implications and 2) the logistics of cleaning up
secrets that are no longer in use.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;Let’s say &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt; &lt;span class="pre"&gt;A&lt;/span&gt;&lt;/code&gt; has 3 disks: one root disk, one ephemeral disk, and
one swap disk. Each disk will have its own secret.&lt;/p&gt;
&lt;p&gt;This table is intended to illustrate the way secrets are handled in various
scenarios.&lt;/p&gt;
&lt;div class="highlight-rst notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Instance or Image  | Disk        | Secret       | Notes                                                |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             | (passphrase) |                                                      |
+====================+=============+==============+======================================================+
&lt;span class="o"&gt;|&lt;/span&gt; Instance A         | disk (root) | Secret 1     | Secret 1, 2, and 3 will be automatically deleted     |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+ by Nova when Instance A is deleted and its disks are |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.eph0   | Secret 2     | destroyed                                            |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+                                                      |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.swap   | Secret 3     |                                                      |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Image Z (snapshot) | disk (root) | Secret 4     | Secret 4 will &lt;span class="ge"&gt;*not*&lt;/span&gt; be automatically deleted and     |
&lt;span class="o"&gt;|&lt;/span&gt; created from       |             | (new secret  | manual deletion will be needed if/when Image Z is    |
&lt;span class="o"&gt;|&lt;/span&gt; Instance A         |             |  is created) | deleted from Glance                                  |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Instance B         | disk (root) | Secret 5     | Secret 5, 6, and 7 will be automatically deleted     |
&lt;span class="o"&gt;|&lt;/span&gt; created from       +-------------+--------------+ by Nova when Instance B is deleted and its disks are |
&lt;span class="o"&gt;|&lt;/span&gt; Image Z (snapshot) | disk.eph0   | Secret 6     | destroyed                                            |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+                                                      |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.swap   | Secret 7     |                                                      |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Instance C         | disk (root) | Secret 8     | Secret 8, 9, and 10 will be automatically deleted    |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+ by Nova when Instance C is deleted and its disks are |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.eph0   | Secret 9     | destroyed                                            |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+                                                      |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.swap   | Secret 10    |                                                      |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Image Y (snapshot) | disk (root) | Secret 8     | Secret 8 is &lt;span class="ge"&gt;*retained*&lt;/span&gt; when Instance C is shelved in |
&lt;span class="o"&gt;|&lt;/span&gt; created by shelve  |             |              | part to prevent the possibility of a change in       |
&lt;span class="o"&gt;|&lt;/span&gt; of Instance C      |             |              | ownership of the root disk secret if, for example,   |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | an admin user shelves a non-admin user's instance.   |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | This approach could be avoided if there is some way  |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | we could create a new secret using the instance's    |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | user/project rather than the shelver's user/project  |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Rescue disk        | disk (root) | Secret 11    | Secret 11 is stashed in the instance's system        |
&lt;span class="o"&gt;|&lt;/span&gt; created by rescue  |             | (new secret  | metadata with key                                    |
&lt;span class="o"&gt;|&lt;/span&gt; of Instance A      |             |  is created) | &lt;span class="s"&gt;``rescue_disk_ephemeral_encryption_secret_uuid``&lt;/span&gt;.    |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | This is done because a BDM record for the rescue     |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | disk is not going to be persisted to the database.   |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="snapshots-of-instances-with-ephemeral-encryption"&gt;
&lt;h4&gt;Snapshots of instances with ephemeral encryption&lt;/h4&gt;
&lt;p&gt;When an instance with ephemeral encryption is snapshotted, a new encryption
secret is created and its key manager secret UUID is kept as an image property
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; and the image is uploaded to Glance.&lt;/p&gt;
&lt;p&gt;When a new instance is created from an encrypted image, the image property
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; is passed down to the lower layers by
storing it in the instance’s system metadata with key
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;. This is done because at the
lower layers (where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;convert&lt;/span&gt;&lt;/code&gt; is called, for example) we no longer
have access to the image metadata and refactoring to pass image metadata to
several lower layer methods, or similar, would be required otherwise.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="snapshots-created-by-shelving-instances-with-ephemeral-encryption"&gt;
&lt;h4&gt;Snapshots created by shelving instances with ephemeral encryption&lt;/h4&gt;
&lt;p&gt;When an instance with ephemeral encryption is shelved, the existing root disk
encryption secret is &lt;em&gt;retained&lt;/em&gt; and will be used to unshelve the instance
later. This is done to prevent a potential change in ownership of the root disk
encryption secret in a scenario where an admin user shelves a non-admin user’s
instance, for example. If a new secret were created owned by the admin user,
the non-admin user who owns the instance will be unable to unshelve the
instance.&lt;/p&gt;
&lt;p&gt;This behavior could be avoided however if there is some way we could create a
new encryption secret using the instance’s user and project rather than the
shelver’s user and project. If that is possible, we would not need to reuse the
encryption secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rescue-disk-images-created-by-rescuing-instances-with-ephemeral-encryption"&gt;
&lt;h4&gt;Rescue disk images created by rescuing instances with ephemeral encryption&lt;/h4&gt;
&lt;p&gt;When rescuing an instance and an encrypted rescue image is
specified, the rescue image secret UUID from the image property will be stashed
in the instance’s system metadata with key
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rescue_image_hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; to pass it down to the
lower layers. This is considered separate from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; which means the encrypted image
from which the instance was created. Another reason to keep it separate is to
avoid confusion for those reading or working on the code.&lt;/p&gt;
&lt;p&gt;A new encryption secret is created when the rescue disk is created and its UUID
is stashed in the instance’s system metadata with key
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rescue_disk_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;. This is done because a block
device mapping record for the rescue disk is not going to be persisted to the
database.&lt;/p&gt;
&lt;p&gt;The corresponding virt driver secret name pattern is
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;instance&lt;/span&gt; &lt;span class="pre"&gt;UUID&amp;gt;_rescue_disk&lt;/span&gt;&lt;/code&gt; and any existing secrets with that name are
deleted by the virt driver when a new rescue is requested.&lt;/p&gt;
&lt;p&gt;The new encryption secret for the rescue disk is deleted from the key manager
and the virt driver secret is also deleted when the instance is unrescued.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="cleanup-of-ephemeral-encryption-secrets"&gt;
&lt;h4&gt;Cleanup of ephemeral encryption secrets&lt;/h4&gt;
&lt;p&gt;Ephemeral encryption secrets are deleted from the key manager and the virt
driver when the corresponding instance is deleted and its disks are destroyed.
The approach is that encryption secrets are &lt;em&gt;only&lt;/em&gt; deleted when the disks
associated with them are destroyed.&lt;/p&gt;
&lt;p&gt;Encryption secrets that are created when a snapshot is created are &lt;em&gt;never&lt;/em&gt;
deleted by Nova. It would only be acceptable to delete the secret if and when
the snapshot image is deleted. Cleanup of secrets whose images have been
deleted from Glance must be deleted manually by the user or an admin.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;At the time of this writing, the newest Ceph release v17 (Quincy) does not
support creating a cloned image with an encryption key different from its
parent. For this reason, copy-on-write cloning will not be enabled for
instances which have specified ephemeral encryption.&lt;/p&gt;
&lt;p&gt;Support for creating a cloned image with an encryption key different from
its parent should be supported in the next release of Ceph.
When we are able to require a Ceph version &amp;gt;= v18, copy-on-write cloning
with ephemeral encryption can be enabled.
See &lt;a class="reference external" href="https://github.com/ceph/ceph/commit/1d3de19"&gt;https://github.com/ceph/ceph/commit/1d3de19&lt;/a&gt; for reference.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; field will be unused and not exposed to end
users initially because of the security and upgrade implications around it.
For the first pass, sensible defaults for the cipher algorithm, cipher
mode, and initialization vector generator algorithm will be hard-coded
instead.&lt;/p&gt;
&lt;p&gt;Encryption options could be exposed to end users in the future when a
proper design which addresses security and handles all upgrade scenarios is
developed.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility trait was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Internal base images stored locally in Nova will not be encrypted at rest.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 05 Oct 2023 00:00:00 </pubDate></item><item><title>Per Process Healthcheck endpoints</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/approved/per-process-healthchecks.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks"&gt;https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In many modern deployment frameworks, there is an expectation that
an application can expose a health-check endpoint so that the binary
status can be monitored. Nova currently does not provide a native way
to inspect the health of its binaries which doesn’t help cloud monitoring
and maintenance. While limited support exists for health checks via
Oslo middleware for our WSGI based API binaries, this blueprint seeks
to expose a local HTTP health-check endpoint to address this
feature gap consistently for all Nova components.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;To monitor the health of a Nova service today requires experience to
develop and implement a series of external heuristics to infer the state
of the service binaries.&lt;/p&gt;
&lt;p&gt;This can be as simple as checking the service status for those with heartbeats
or can comprise monitoring log output via a watchdog and restarting
the service if no output is detected after a protracted period.
Processing the logs for known error messages and executing a remediation script
or other methods that are easy to do incorrectly are also common.&lt;/p&gt;
&lt;p&gt;This is also quite unfriendly to new Nova users who have not gained enough
experience with operating Nova to know what warning signs they should look
for such as inability to connect to the message bus. Nova developers however
do know what some of the important health indicators are and can expose
those as a local health-check endpoint that operators can use instead.&lt;/p&gt;
&lt;p&gt;The existing Oslo middleware does not address this problem statement because:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;It can only be used by the API and metadata binaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The middleware does not tell you the service is alive if its hosted by a
WSGI server like Apache since the middleware is executed independently from
the WSGI application. i.e. the middleware can pass while the nova-api can’t
connect to the DB and is otherwise broken.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Oslo middleware in detailed mode leaks info about the host Python
kernel, Python version and hostname which can be used to determine in the
host is vulnerable to CVEs which means it should never be exposed to the
Internet. e.g.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Linux-5.15.2-xanmod1-tt-x86_64-with-glibc2.2.5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;python_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3.8.12 (default, Aug 30 2021, 16:42:10) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[GCC 10.3.0]'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want a simple REST endpoint I can consume to know
if a Nova process is healthy.&lt;/p&gt;
&lt;p&gt;As an operator I want this health check to not impact the performance of the
service so it can be queried frequently at short intervals.&lt;/p&gt;
&lt;p&gt;As a deployment tool implementer, I want the health check to be local with no
dependencies on other hosts or services to function so I can integrate it with
service managers such as systemd or a container runtime like Docker.&lt;/p&gt;
&lt;p&gt;As a packager, I would like the use of the health check endpoints to not
require special clients or packages to consume them. cURL, socat, or netcat
should be all that is required to connect to the health check and retrieve the
service status.&lt;/p&gt;
&lt;p&gt;As an operator I would like to be able to use health-check of the Nova API and
metadata services to manage the membership of endpoints in my load-balancer
or reverse proxy automatically.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="definitions"&gt;
&lt;h3&gt;Definitions&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TTL&lt;/span&gt;&lt;/code&gt;: The time interval for which a health check item is valid.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;: all health indicators are passing and their TTLs have not expired.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;: any health indicator has an expired TTL or where there is
a partial transient failure.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;: any health indicator is reporting an error or all TTLs are expired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="warn-vs-fail"&gt;
&lt;h3&gt;Warn vs fail&lt;/h3&gt;
&lt;p&gt;In general if any of the health check indicators are failing then the service
should be reported as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; however if the specific error condition is
recoverable or only a partial failure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state can and should be
used.&lt;/p&gt;
&lt;p&gt;An example of this is a service that has lost a connection to the message bus.
When the connection is lost it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state, if the first
attempt to reconnect fails it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state. Transient
failure should be considered warning but persistent errors should be escalated
to failures.&lt;/p&gt;
&lt;p&gt;In many cases external management systems will treat &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; as
equivalent and raise an alarm or restart the service. While this spec does
not specify how you should recover from a degraded state, it is
important to include a human readable description of why the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state was entered.&lt;/p&gt;
&lt;p&gt;Services in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state are still considered healthy in most cases but
they may be about to fail soon or be partially degraded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;Code changes&lt;/h3&gt;
&lt;p&gt;A new top-level Nova health check module will be created to encapsulate the
common code and data structure required to implement this feature.&lt;/p&gt;
&lt;p&gt;A new health check manager class will be introduced which will maintain the
health-check state and all functions related to retrieving, updating and
summarizing that state.&lt;/p&gt;
&lt;p&gt;The health check manager will be responsible for creating the health check
endpoint when it is enabled in the nova.conf and exposing the health check
over HTTP.&lt;/p&gt;
&lt;p&gt;The initial implementation will support HTTP over TCP with optional support for
UNIX domain sockets as a more secure alternative to be added later.
The HTTP endpoint in both cases will be unauthenticated and the response will
be in JSON format.&lt;/p&gt;
&lt;p&gt;A new HealthcheckStausItem data class will be introduced to store an
individual health check data-point. The HealtcheckStatusItem will contain
the name of the health check, its status, the time it was recorded,
and an optional output string that should be populated if the
status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A new decorator will be introduced that will automatically retrieve the
reference to the healthcheck manager from the Nova context object and update
the result based on whether the function decorated raises an exception or not.
The exception list and healthcheck item name will be specifiable.&lt;/p&gt;
&lt;p&gt;The decorator will accept the name of the health check as a positional argument
and include the exception message as the output of the health check on failure.
Note that the decorator will only support the pass or fail status for
simplicity; where warn is appropriate a manual check should be written.
If multiple functions act as indicators of the same capability the same name
should be used.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_other_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default all exceptions will be caught and re-raised by the decorator.&lt;/p&gt;
&lt;p&gt;The new REST health check endpoint exposed by this spec will initially only
support one URL path &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt;. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; endpoint will include a
&lt;cite&gt;Cache-Control: max-age=&amp;lt;ttl&amp;gt;&lt;/cite&gt; header as part of its response which can
optionally be consumed by the client.&lt;/p&gt;
&lt;p&gt;The endpoint may also implement a simple incrementing etag at a later date
once the initial implementation is complete, if required.
Initially adding an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; is not provided as the response is expected to be
small and cheap to query, so etags do not actually provide much benefit form
a performance perspective.&lt;/p&gt;
&lt;p&gt;If implemented, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; will be incremented whenever the service state
changes and will reset to 0 when the service is restarted.&lt;/p&gt;
&lt;p&gt;Additional URL paths may be supported in the future, for example to retrieve
the running configuration or trigger the generation of Guru Meditation Reports
or enable debug logging. However, any endpoint beyond &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; is out of
scope of this spec. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; is not used for health check response to facilitate
additional paths in the future.&lt;/p&gt;
&lt;section id="example-output"&gt;
&lt;h4&gt;Example output&lt;/h4&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"e3c22423-cd7a-47dc-b6e9-e18d1a8b3bdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"api_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="n"&gt;Sevice&lt;/span&gt; &lt;span class="n"&gt;Unavailable&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0a47dceb-11b1-4d94-8b9c-927d998be320"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-compute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"hypervisor"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
             &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:05:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s2"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Libvirt Error: ..."&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of maintaining the state of the process in a data structure and
returning the cached state we, could implement the health check as a series of
active probes such as checking the DB schema version to ensure we can access
it or making a ping RPC call to the cell conductor or our own services RPC
endpoint.&lt;/p&gt;
&lt;p&gt;While this approach has some advantages it will have a negative performance
impact if the health-check is queried frequently or in a large deployment where
infrequent queries may still degrade the DB and message bus performance due to
the scale of the deployment.&lt;/p&gt;
&lt;p&gt;This spec initially suggested using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OK&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Degraded&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Faulty&lt;/span&gt;&lt;/code&gt; as the
values for the status field. These were updated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; to align with the draft IETF RFC for health check response format for
HTTP APIs &lt;a class="reference external" href="https://tools.ietf.org/id/draft-inadarei-api-health-check-06.html"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The Nova context object will be extended to store a reference to the
health check manager.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While this change will expose a new REST API endpoint it will not be
part of the existing Nova API.&lt;/p&gt;
&lt;p&gt;In the Nova API the /health check route will not initially be used to allow
those that already enable the Oslo middleware to continue to do so.
In a future release Nova reserves the right to add a /health check endpoint
that may or may not correspond to the response format defined in Oslo.
A translation between the Oslo response format and the health check module
may be provided in the future but it is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The new health check endpoint will be disabled by default.
When enabled it will not provide any authentication or explicit access control.
The documentation will detail that when enabled, the TCP endpoint should be
bound to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;localhost&lt;/span&gt;&lt;/code&gt; and that file system permission should be used to secure
the UNIX socket.&lt;/p&gt;
&lt;p&gt;The TCP configuration option will not prevent binding it to a routable IP if
the operator chooses to do so. The intent is that the data contained in the
endpoint will be non-privileged however it may contain hostnames/FQDNs or other
infrastructure information such as service UUIDs, so it should not be
accessible from the Internet.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While the health checks will use the ability to send notification as an input
to determine the health of the system, this spec will not introduce any new
notifications and as such it will not impact the Notification subsystem in
Nova. New notifications are not added as this would incur a performance
overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;At present, it is not planned to extend the Nova client or the unified client
to query the new endpoint. cURL, socat, or any other UNIX socket or TCP HTTP
client can be used to invoke the endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;We expect there to be little or no performance impact as we will be taking a
minimally invasive approach to add health indicators to key functions
which will be cached in memory. While this will slightly increase memory usage
there is no expected impact on system performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new config section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;healthcheck&lt;/span&gt;&lt;/code&gt; will be added in the nova.conf&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uri&lt;/span&gt;&lt;/code&gt; config option will be introduced to enable the health check
functionality. The config option will be a string opt that supports a
comma-separated list of URIs with the following format&lt;/p&gt;
&lt;p&gt;uri=&amp;lt;scheme&amp;gt;://[host:port|path],&amp;lt;scheme&amp;gt;://[host:port|path]&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The URI should be limited to the following characters &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[a-zA-Z0-9_-]&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;,&lt;/span&gt;&lt;/code&gt; is reserved as a separation character, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; may only be used in IPv4
addresses, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt; is reserved for port separation unless the address is an
IPv6 address. IPv6 addresses must be enclosed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[&lt;/span&gt;&lt;/code&gt; and  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;]&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; may
be used with the UNIX protocol however relative paths are not supported.
These constraints and the parsing of the URI will be enforced and provided by
the RFC3986 lib &lt;a class="reference external" href="https://pypi.org/project/rfc3986/"&gt;https://pypi.org/project/rfc3986/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt; IntOpt will be added with a default value of 300 seconds.
If set to 0, the time to live of a health check item will be infinite.
If the TTL expires, the state will be considered unknown and the healthcheck
item will be discarded.&lt;/p&gt;
&lt;p&gt;A cache_control IntOpt will be provided to set the max-age value in the
cache_control header. By default it will have the same max-age as the TTL
config option. Setting this to 0 will disable the reporting of the header.
Setting this to -1 will report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Cache-Control:&lt;/span&gt; &lt;span class="pre"&gt;no-cache&lt;/span&gt;&lt;/code&gt;.
Any other positive integer value will be used as the max-age.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers should be aware of the new decorator and consider whether it should
be added to more functions, if that function is an indicator of the system’s
health. Failures due to interactions with external systems such as Neutron port
binding external events should be handled with caution. While failure to
receive a port binding event will likely result in the failure to boot a VM, it
should not be used as a health indicator for the nova-compute agent. This is
because such a failure may be due to a failure in Neutron, not Nova. As such,
other operations such as VM snapshot may be unaffected and the Nova compute
service may be otherwise healthy. Any failure to connect to a non-OpenStack
service such as the message bus, hypervisor, or database should be treated as a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; health indicator if it prevents the Nova binary from
functioning correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce decorator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend context object to store a reference to health check manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose TCP endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose UNIX socket endpoint support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested entirely with unit and functional tests, however,
Devstack will be extended to expose the endpoint and use it to determine
whether the Nova services have started.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The config options will be documented in the config reference
and a release note will be added for the feature.&lt;/p&gt;
&lt;p&gt;A new health check section will be added to the admin docs describing
the current response format and how to enable the feature and its intended
usage. This document should be evolved whenever the format changes or
new functionality is added beyond the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Yoga PTG topic:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415"&gt;https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 03 Oct 2023 00:00:00 </pubDate></item><item><title>Ironic Shards</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ironic-shards.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ironic-shards"&gt;https://blueprints.launchpad.net/nova/+spec/ironic-shards&lt;/a&gt;&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The series was implemented but eventually reverted due to some bug
that was found late. It should be again merged in the next release,
ie. 2024.1. That said, we kept the deprecation for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ironic]\peer_list&lt;/span&gt;&lt;/code&gt; config option, which was explained below in
&lt;a class="reference internal" href="#config-changes-and-deprecations"&gt;Config changes and Deprecations&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova’s Ironic driver involves a single nova-compute service managing
many compute nodes, where each compute node record maps to an Ironic node.
Some deployments support 1000s of ironic nodes, but a single nova-compute
service is unable to manage 1000s of nodes and 1000s of instances.&lt;/p&gt;
&lt;p&gt;Currently we support setting a partition key, where nova-compute only
cares about a subset of ironic nodes, those associated with a specific
conductor group. However, some conductor groups can be very large,
servered by many ironic-conductor services.&lt;/p&gt;
&lt;p&gt;To help with this, Nova has attempted to dynamically spread ironic
nodes between a set of nova-compute peers. While this work some of
the time, there are some major limitations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;when one nova-compute is down, only unassigned ironic nodes can
move to another nova-compute service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;i.e. when one nova-compute is down, all ironic nodes with nova instances
associated with the down nova-compute service are unable to be
managed, i.e. reboot will fail&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;moreover, when the old nova-compute comes back up, which might take
some time, there are lots of bugs as the hash ring slowly rebalances.
In part because every nova-compute fetches all nodes, in a large enough
cloud, this can take over 24 hours.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This spec is about tweaking the way we shard Ironic compute nodes.
We need to stop violating deep assumptions in the compute manager
code by moving to a more static ironic node partitions.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Any users of the ironic driver that have more than one
nova-compute service per conductor group should move to an
active-passive failover mode.&lt;/p&gt;
&lt;p&gt;The new static sharding will be of paritcular interest for clouds
with ironic conductor groups that are greater than around
1000 baremetal nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We add a new configuration option:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;[ironic] shard_key&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, there will be no shard_key set, and we will continue to
expose all ironic nodes from a single nova-compute process.
Mostly, this is to keep things simple for smaller deployments,
i.e. when you have less than 500 ironic nodes.&lt;/p&gt;
&lt;p&gt;When the operator sets a shard_key, the compute-node process will
use the shard_key when querying a list of nodes in Ironic.
We must never try to list all Ironic nodes when
the Ironic shard key is defined in the config.&lt;/p&gt;
&lt;p&gt;When we look up a specific ironic node via a node uuid or
instance uuid, we should not restrict that to either the shard key
or conductor group.&lt;/p&gt;
&lt;p&gt;Similar to checking the instance uuid is still present on the Ironic
node before performing an action, or ensuring there is no instance uuid
before provisioning, we should also check the node is in the correct
shard (and conductor group) before doing anything with that Ironic node.&lt;/p&gt;
&lt;section id="config-changes-and-deprecations"&gt;
&lt;h3&gt;Config changes and Deprecations&lt;/h3&gt;
&lt;p&gt;We will keep the option to target a specific conductor group,
but this option will be renamed from partition_key to conductor_group.
This is addative to the shard_key above, the target ironic nodes are
those in both the correct &lt;cite&gt;shard_key&lt;/cite&gt; and the correct &lt;cite&gt;conductor_group&lt;/cite&gt;,
when both are configured.&lt;/p&gt;
&lt;p&gt;We will deprecate the use of the &lt;cite&gt;peer_list&lt;/cite&gt;.
We should log a warning when the hash ring is being used,
i.e. when it has more than one member added to the hash ring.&lt;/p&gt;
&lt;p&gt;In addtion, we need the logic that tries to move Compute Nodes
to never work unless the peer_list is larger than one. More details
in the data model impact section.&lt;/p&gt;
&lt;p&gt;When deleting a ComputeNode object, we need to have the driver
confirm that is safe. In the case of Ironic we will check to see if
the configured Ironic has a node with that uuid, searching across all
conductor groups and all shard keys. When the ComputeNode object is not
deleted, we should not delete the entry in placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="nova-manage-move-ironic-node"&gt;
&lt;h3&gt;nova-manage move ironic node&lt;/h3&gt;
&lt;p&gt;We will create a new nova-manage command:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
    &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This command will do the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Find the ComputeNode object for this ironic-node-uuid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if the ComputeNode type does not match the ironic driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the related Service object for the above ComputeNode
(i.e. the host)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if the service object is not reported as down, and
has not also been put into maintanance. We do not require
forced down, because we might only be moving a subset of
nodes associated with this nova-compute service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the Service object for the destination service host exists&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find all non-deleted instances for this (host,node)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if there is more than 1 non-deleted instance found.
It is OK if we find zero or 1 instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In one DB transaction:
move the ComputeNode object to the destination service host and
move the Instance (if there is one) to the destination service host&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above tool is expected to be used as part of this wider process
of migrating from the old peer_list to the new shard key. There are
two key scearios (although the tool may help operator recover from
other issues as well):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;moving from a peer_list to a single nova-compute&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;moving from peer_list to shard_key, while keeping multiple nova-compute
proccesses (for a single conductor group)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="migrate-from-peer-list-to-single-nova-compute"&gt;
&lt;h3&gt;Migrate from peer_list to single nova-compute&lt;/h3&gt;
&lt;p&gt;Small deployments (i.e. less than 500 ironic nodes)
are recommended to move from a peer_list of, for example,
three nova-compute services, to a single nova-compute service.
On failure of the nova-compute service, operators can either manually start
the processes on a new host, or use an automatic active-passive HA scheme.&lt;/p&gt;
&lt;p&gt;The process would look something like this:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ironic and nova both default to an empty_shard key by default,
such that all ironic nodes are in the same default shard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;start a new nova-compute service running the ironic driver,
ideally with a syntheic value for &lt;cite&gt;[DEFAULT]host&lt;/cite&gt; e.g. &lt;cite&gt;ironic&lt;/cite&gt;
This will log warnings about the need to use the nova-compute
migration tool before being able to manage any nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop all existing nova-compute services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mark them as forced-down via the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now loop around all ironic nodes and call this, assuming your
nova-compute service has its host value of just &lt;cite&gt;ironic&lt;/cite&gt;:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service ironic&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The periodic tasks in the new nova-compute service will gradually
pick up the new ComputeNodes, and will start being able to recieve
commands such a reboot for all the moved instances.&lt;/p&gt;
&lt;p&gt;While you could start the new nova-compute service after
having migrated all the ironic compute nodes, but that would
lead to higher downtime during the migration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migrate-from-peer-list-to-shard-key"&gt;
&lt;h3&gt;Migrate from peer_list to shard_key&lt;/h3&gt;
&lt;p&gt;The proccess to move from the hash key based peer_list to the static
shard_key from ironic is very similar to the above process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Set the shard_key on all your ironic nodes, such that you can spread
the nodes out between your nova-compute processes,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start your new nova compute processes, one for each &lt;cite&gt;shard_key&lt;/cite&gt;,
possibly setting a synthetic &lt;cite&gt;[DEFAULT]host&lt;/cite&gt; value that matches the
&lt;cite&gt;my_shard_key&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shutdown all the older nova-compute processs with &lt;cite&gt;[ironic]peer_list&lt;/cite&gt; set&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark those older services as in maintainance via the Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each shard_key in Ironic, work out which service host you have mapped
each one to above, then run this for each ironic node uuid in the shard:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service my_shard_key&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the old services via the Nova API, now there are no instances
or compute nodes on those services&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While you could start the new nova-compute services after the migration,
that would lead to a slightly longer downtime.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="adding-new-compute-nodes"&gt;
&lt;h3&gt;Adding new compute nodes&lt;/h3&gt;
&lt;p&gt;In general, there is no change when adding nodes into existing
shards.&lt;/p&gt;
&lt;p&gt;Similarly, you can add a new nova-compute process for a new shard
and then start to fill that up with nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="move-an-ironic-node-between-shards"&gt;
&lt;h3&gt;Move an ironic node between shards&lt;/h3&gt;
&lt;p&gt;When removing nodes from ironic at the end of their life, or
adding large numbers of new nodes, you may need to rebalance
the shards.&lt;/p&gt;
&lt;p&gt;To move some ironic nodes, you need to move the nodes in
groups associated with a specific nova-compute process.
For each nova-compute and the associated ironic nodes you
want to move to a different shard you need to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Shutdown the affected nova-compute process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put nova-compute services into in maintanance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Ironic API update the shard key on the Ironic node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now move each ironic node to the correct new nova-compute
process for the shard key it was moved into:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service my_shard_key&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now unset maintanance mode for the nova-compute,
and start that service back up&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="move-shards-between-nova-compute-services"&gt;
&lt;h3&gt;Move shards between nova-compute services&lt;/h3&gt;
&lt;p&gt;To move a shard between nova-compute services, you need to
replace the nova-compute process with a new one:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ensure the destination nova-compute is configured with the
shard you want to move, and is running&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop the nova-compute process currently serving the shard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;force-down the service via the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for each ironic node uuid in the shard call nova-manage
to move it to the new nova-compute process&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could require nova-compute processes to be explicitly forced down,
before allowing the nova-manage to move the ironic nodes about,
in a similar way to evacuate.
But this creates problems when trying to re-balance shards as you
remove nodes at the end of their life.&lt;/p&gt;
&lt;p&gt;We could consider a list of shard keys, rather than a single shard key
per nova-compute. But for this first version, we have chosen the simpler
path, that appears to have few limitations.&lt;/p&gt;
&lt;p&gt;We could attempt to keep fixing the hash ring recovery within the ironic
driver, but its very unclear what will break next due to all the deep
assumptions made about the nova-compute process. The specific assumptions
include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;when nova-compute breaks, its usually the hypervisor hardware that
has broken, which includes all the nova servers running on that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all locking and management of a nova server object is done by the
currently assigned nova-compute node, and this is only ever changed
by explict move operations like resize, migrate, live-migration
and evacuate. As such we can use simple local locks to ensure
concurrent operations don’t conflict, along with DB state checking.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A key thing we need to ensure is that ComputeNode objects are only
automatically moved between service objects when in legacy hash ring mode.
Currently, this only happens for unassigned ComputeNodes.&lt;/p&gt;
&lt;p&gt;In this new explicit shard mode, only nova-manage is able to move
ComputeNode objects. In addtion, nova-manage will also move associated
instances. However, similar to evacuate, this will only be allowed
when the currently associated service is forced down.&lt;/p&gt;
&lt;p&gt;Note, this applies when a nova-compute finds a ComputeNode that is should
own, but the Nova database says its already owned by a difference service.
In this scenario, we should log a warning to the operator
to ensure they have migrated that ComputeNode from its old location
before this nova-compute service is able to manage it.&lt;/p&gt;
&lt;p&gt;In addition, we should ensure we only delete a ComputeNode object
when the driver explictly says its safe to delete. In the case of
the Ironic driver, we should ensure the node no longer exists in
Ironic, being sure to search across all shards.&lt;/p&gt;
&lt;p&gt;This is all very related this spec on robustfying
the Compute Node and Service object relationship:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/853837"&gt;https://review.opendev.org/c/openstack/nova-specs/+/853837&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will experience a more reliable Ironic and Nova integration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;It should help users more easily support large ironic deployments
integrated with Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;We will rename the “partition_key” configuration to be expliclity
“conductor_group”.&lt;/p&gt;
&lt;p&gt;We will deprecate the peer list key. When we start up and see
anything set, we ommit a warning about the bugs in using this
legacy auto sharding, and recomend moving to the explicit sharding.&lt;/p&gt;
&lt;p&gt;There is a new &lt;cite&gt;shard_key&lt;/cite&gt; config, as descirbed above.&lt;/p&gt;
&lt;p&gt;There is a new nova_manage CLI command to move Ironic compute nodes
on forced-down nova-compute services to a new one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For those currenly using peer_list, we need to document how they
can move to the new sharding approach.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;JayF&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Feature liaison: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;rename conductor group partition key config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;deprecate peer_list config, with warning log messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add compute node move and delete protections, when peer_list not used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add new shard_key config, limit ironic node list using shard_key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add nova-manage tool to move ironic nodes between compute services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;document operational processes around above nova-manage tool&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The deprecation of the peer list can happen right away.&lt;/p&gt;
&lt;p&gt;But the new sharding depends on the Ironic shard key getting added:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/ironic-specs/+/861803"&gt;https://review.opendev.org/c/openstack/ironic-specs/+/861803&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally we add this into Nova after robustify compute node has landed:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/842478"&gt;https://review.opendev.org/c/openstack/nova/+/842478&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We need some functional tests for the nova-manage command to ensure
all of the safty guards work as expected.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A lot of docs needed for the Ironic driver on the operational
procedures around the shard_key.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 27 Sep 2023 00:00:00 </pubDate></item><item><title>Use extend volume completion action</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/assisted-volume-extend.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend"&gt;https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume
action that has been proposed for Cinder in &lt;a class="footnote-reference brackets" href="#id12" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, to provide feedback on
success or failure when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server events.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many remotefs-based volume drivers in Cinder use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;resize&lt;/span&gt;&lt;/code&gt;
command to extend volume files.
However, when the volume is attached to a guest, QEMU will lock the file and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt;&lt;/code&gt; will be unable to resize it.&lt;/p&gt;
&lt;p&gt;In this case, only the QEMU process holding the lock can resize the volume,
which can be triggered through the QEMU monitor command &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is currently no adequate way for Cinder to use this feature, so the NFS,
NetApp NFS, Powerstore NFS, and Quobyte volume drivers all disable extending
attached volumes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I want to extend a NFS/NetApp NFS/Powerstore NFS/Quobyte volume
while it is attached to an instance and I want the volume size and status to
reflect the success or failure of the operation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova’s libvirt driver uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command when handling the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event, to inform QEMU that the size of an
attached volume has changed.
It is in principle also capable of extending a volume file, but is currently
unable to provide feedback to Cinder on the success of the operation.&lt;/p&gt;
&lt;p&gt;Currently, Cinder will send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event to
Nova only after it has finalized the extend operation and reset the volume
status from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;a class="footnote-reference brackets" href="#id12" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, Cinder will allow volume drivers to hold off finalizing the extend
operation and leave the volume status as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, until after it has
send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event and received feedback from Nova in form of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action, with an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; argument
indicating whether to finalize or to roll back the operation.&lt;/p&gt;
&lt;p&gt;This will currently affect only the volume drivers mentioned above, all of
which did not previously support online extend.
All other drivers will continue to send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event after
finalizing the operation and resetting to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt; status, and will not
expect a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action.&lt;/p&gt;
&lt;section id="compute-agent"&gt;
&lt;h3&gt;Compute Agent&lt;/h3&gt;
&lt;p&gt;Nova’s compute agent will use the volume status to differentiate between the
two behaviors when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the volume status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, then it will attempt to read
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; from the volume’s metadata and use this value as the
new size of the volume, instead of the volume size field.&lt;/p&gt;
&lt;p&gt;After successfully extending the volume, it will call the extend volume
completion action of the volume, with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;false&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If anything goes wrong, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; being missing from the
metadata, or being smaller than the current size of the volume, it will
log the error and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;, so Cinder can roll back the operation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For any other volume status, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, the event will be handled
as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="api"&gt;
&lt;h3&gt;API&lt;/h3&gt;
&lt;p&gt;Nova’s API will introduce a new microversion, so that Cinder can make sure the
new behavior is available, before leaving an extend operation unfinished.&lt;/p&gt;
&lt;p&gt;To handle older compute agents during a rolling upgrade, the API will also
check the compute service version of the target agent when receiving a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event with the new microversion.
If a target compute agent is too old to support the feature, the API will
discard the event and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A previous change tried to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event
to support online extend for the NFS driver &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but did not rely on
feedback from Nova to Cinder at all.
Instead, it would just set the new size of the volume, change the status
back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, notify Nova, and hope for the best.&lt;/p&gt;
&lt;p&gt;If anything went wrong on Nova’s side, this would still result in a volume
state indicating that the operation was successful, which is not acceptable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A previous version of this spec proposed a new synchronous API in Nova &lt;a class="footnote-reference brackets" href="#id11" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;,
that would directly call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CompVirtAPI.extend_image&lt;/span&gt;&lt;/code&gt; of the nova-compute
instance managing the guest that a volume was attached to.
This API would provide a single mechanism to trigger the resize operation,
communicate the new size to Nova, and get feedback on the success of the
operation.&lt;/p&gt;
&lt;p&gt;The problem with a synchronous API is, that RPC and API timeouts limit the
maximum time an extend operation can take.
For QEMU, this seemed to be acceptable, because storage preallocation is
hard disabled for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command, and because all currently
plausible file systems support sparse file operations.&lt;/p&gt;
&lt;p&gt;However, this may not be true for other volume or virt drivers that might
require this API in the future.
It would also break with the established pattern of asynchronous
coordination between Nova and Cinder, which includes the assisted snapshot
and volume migration features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Following this pattern, we could make the proposed API asynchronous and use
a new callback in Cinder, similar to Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-assisted-volume-snapshots&lt;/span&gt;&lt;/code&gt;
API, which uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-update_snapshot_status&lt;/span&gt;&lt;/code&gt; snapshot action to provide
feedback to Cinder.&lt;/p&gt;
&lt;p&gt;The function of the new Nova API would then just be to trigger the operation
and to communicate the new size.
The question is then, whether that warrants adding a new API to Nova, since
there are existing mechanisms that could be used for either.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The existing mechanism for triggering the extend operation in Nova is of
course the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event.
Using it for this purpose, as this spec proposes, requires the target size
to be transferred separately, because external server events only have a
single text field that is freely usable, which for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt;
is already used for the volume ID.&lt;/p&gt;
&lt;p&gt;Besides storing it in the admin metadata, as &lt;a class="footnote-reference brackets" href="#id12" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and this spec propose,
there is also the option of updating the size field of the volume, as &lt;a class="footnote-reference brackets" href="#id10" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
was essentially doing.&lt;/p&gt;
&lt;p&gt;This would require the volume size field to be reset on a failure.
If an error response from Nova was lost, the volume would just keep the new
size.
We would need to extend &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-reset_status&lt;/span&gt;&lt;/code&gt; to allow a size reset, or
something similar to clean up volumes like this.
This would be possible, but updating the size field only after the volume
was successfully extended seems like a cleaner solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could also extend the external server event API to accept additional data
for events, and use this to communicate the new size to Nova.&lt;/p&gt;
&lt;p&gt;This option was judged favorably by reviewers on the previous version of
this spec, &lt;a class="footnote-reference brackets" href="#id11" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but it would be a more complex change to the Nova API.&lt;/p&gt;
&lt;p&gt;However, if additional data fields become available in a future version of
the external server event API, it would be a relatively minor change to use
this instead of volume metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The behavior of the external server event API will change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If Nova receives a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event, and the referenced volume has
status of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, Nova will look for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; key in
the volume metadata, and use this instead of the volume size field as the
target size to update the block device mapping and to pass to the virt
driver’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_volume&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Nova will also attempt to call Cinder’s new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt;
volume action proposed in &lt;a class="footnote-reference brackets" href="#id12" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to let Cinder know if the operation was
successful or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, the API will behave as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Checking the target compute service version allows the API to handle rolling
upgrades gracefully.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kgube&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None yet&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the external server event API to check the target compute service
version for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeVirtAPI.extend_volume&lt;/span&gt;&lt;/code&gt; method to follow the behavior
outlined in &lt;a class="reference internal" href="#compute-agent"&gt;Compute Agent&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt NFS job in the Nova gate to validate online extend.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The extend volume completion action &lt;a class="footnote-reference brackets" href="#id12" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We should test that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; gets called correctly
in all possible error or success condition if a volume has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;
status.&lt;/p&gt;
&lt;p&gt;We should test the case that the call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; fails.&lt;/p&gt;
&lt;p&gt;We also need to test that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; continues to be handled correctly
for volumes not in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; status.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new behavior of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event should be added to the
documentation of the external server event API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/739079"&gt;https://review.opendev.org/c/openstack/cinder/+/739079&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id4"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/855490/6"&gt;https://review.opendev.org/c/openstack/nova-specs/+/855490/6&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id9"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder-specs/+/877230"&gt;https://review.opendev.org/c/openstack/cinder-specs/+/877230&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id13"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>VirtIO PackedRing Configuration support</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/virtio-packedring-configuration-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virtio-packedring-configuration-support"&gt;https://blueprints.launchpad.net/nova/+spec/virtio-packedring-configuration-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to expose the LibVirt &lt;cite&gt;packed&lt;/cite&gt; option that allows a
guest to negotiate support for the VirtIO packed-ring feature. This blueprint
is used to solicit community’s input.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;VM using a Virtio-net paravirtual network device uses Virtual queues (virtqs)
to send and recveive data between the virtio-net driver and the virtual or
physical backed. The VirtIO standard originally defined a single type of virtq
called split-ring queue. The latest edition of the standard (v1.1) adds a
different type of the virtq, called packed-ring queue. A different layout of
queue elements allows to increase the performance in both virtual and physical
backeds.&lt;/p&gt;
&lt;p&gt;Split-ring support is the default option in VirtIO. Backends supporting
the packed-ring virtqs advertise this by setting the &lt;cite&gt;VIRTIO_F_RING_PACKED&lt;/cite&gt;
feature bit during the feature negotiation. A guest driver then chooses the
virtq layout based on what it supports. As both options are identical features
wise, and the packed-ring is more efficient, the latter is typically chosen.&lt;/p&gt;
&lt;p&gt;Qemu added support for the packed virtqs in v4.2 and LibVirt in v6.3. Qemu and
LibVirt supports the packed-ring virtqs via the &lt;cite&gt;packed&lt;/cite&gt; option. However, note
that this option &lt;em&gt;does not&lt;/em&gt; force the VM to use the packed-ring virtq. It acts
as a mask, allowing the backed to advertise the support when set. The driver in
the VM is still responsible for choosing the layout of virtqs.&lt;/p&gt;
&lt;p&gt;This blueprint proposes to add a Nova flavor extra_spec and Glance image
property, that sets the &lt;cite&gt;packed&lt;/cite&gt; option to &lt;cite&gt;true&lt;/cite&gt; on the node. This way all VMs
running on the node are allowed to choose the virtq layout based on what is
offered by the backed, rather than being froced to use split-ring.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to benefit from the increase in the virtio-net
performance, by using a more efficient virtq structure.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_virtio_packed_ring&lt;/span&gt;&lt;/code&gt; for image property and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:virtio_packed_ring&lt;/span&gt;&lt;/code&gt; for flavor extra specs.
Users will control the packed virtqueue feature, and be able to disable
it if desired.&lt;/p&gt;
&lt;p&gt;hw_virtio_packed_ring=true|false  (default false)
hw:virtio_packed_ring=true|false  (default false)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide new compute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_NET_VIRTIO_PACKED&lt;/span&gt;&lt;/code&gt; capablity trait.
This trait can be required/forbidden by user. Nova-compute agent
will automatically set this trait to the resource provider summary
if libvirt version is higher than 6.3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This spec will update scheduling process. ALL_REQUEST_FILTERS will be
extended with new filter packed_virtqueue_filter. It will update RequestSpec
with new trait in case if image property or flavor extra_spec is enabled to
avoid migration to the node without packed virtqueue feature support.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Leave as-is, operator will not have additional performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;VMs using virtio-net will see an increase in performance. The increase can be
anywhere between 10/20% (see DPDK Intel Vhost/virtio perf. reports) and 75%
(using Napatech SmartNICs).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This spec will update scheduling process. New trait
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_NET_VIRTIO_PACKED&lt;/span&gt;&lt;/code&gt; will be set to the resource provider trait list
automatically if this feaure is supported on the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New Functional and Unit tests will be provided.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;justas_napa on IRC and Gerrit&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The feature can be implemented by the Napatech devs &lt;a class="reference external" href="mailto:dvo-plv%40napatech.com"&gt;dvo-plv&lt;span&gt;@&lt;/span&gt;napatech&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt; and
&lt;a class="reference external" href="mailto:obu-plv%40napatech.com"&gt;obu-plv&lt;span&gt;@&lt;/span&gt;napatech&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Sean Mooney (sean-k-mooney)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;N/A at this stage.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Configuration options reference will require an update.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;VirtIO standard:
&lt;a class="reference external" href="https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html"&gt;https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LibVirt Domain XML reference
&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#virtio-related-options"&gt;https://libvirt.org/formatdomain.html#virtio-related-options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>Allow local scaphandre directory to be mapped to an instance using virtiofs</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/virtiofs-scaphandre.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virtiofs-scaphandre"&gt;https://blueprints.launchpad.net/nova/+spec/virtiofs-scaphandre&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Scaphandre is a tool that can be used to measure compute and VM power
consumption down to processes. (&lt;a class="reference external" href="https://github.com/hubblo-org/scaphandre"&gt;https://github.com/hubblo-org/scaphandre&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;If you want to know more, the BBC folks proposed an interesting use case
to create environmental dashboards:
&lt;a class="reference external" href="https://superuser.openstack.org/articles/environmental-reporting-dashboards-for-openstack-from-bbc-rd/"&gt;https://superuser.openstack.org/articles/environmental-reporting-dashboards-for-openstack-from-bbc-rd/&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, this is not possible to get consumption per VM as scaphandre
requires a directory on the compute node accessible into running VMs.
This directory contains data required by the scaphandre instance (guest agent)
running on the VM to correctly reports VM and VM associated processes
consumption.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://hubblo-org.github.io/scaphandre-documentation/how-to_guides/propagate-metrics-hypervisor-to-vm_qemu-kvm.html"&gt;Scaphandre proposed solution&lt;/a&gt; to get these data is to mount the directory
using virtiofs in the VM.
However, the user can not do that, as it requires the VM XML definition file
to be modified. Nova fully manages this file, and as a result, only nova
can change it.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user, I want to know the consumption of my compute node and drill
down to VM and VM processes individual consumption.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an administrator, I want to allow this usage but make sure the user
can mount only the configured required directory. I also want not to leak
cloud design insights.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To simplify specifications, the feature will be named
&lt;cite&gt;virtiofs-scaphandre&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Although this feature is implemented to support scaphandre, other tools
could require this need. So the implementation will try to be as generic
as possible.&lt;/p&gt;
&lt;p&gt;This change relies partially on
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/libvirt-virtiofs-attach-manila-shares.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/libvirt-virtiofs-attach-manila-shares.html&lt;/a&gt;
specification to build the VM XML file including virtiofs settings
(mostly &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/833090"&gt;driver part&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This implies the same requirements and limitation.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;=5.0 and libvirt &amp;gt;= 6.2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Associated instances use file backed memory or huge pages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live migrate an instance will not be supported as life attach and detach has
landed only “recently” in &lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1897708"&gt;libvirt&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Change description:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a compute configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_local_fs&lt;/span&gt;&lt;/code&gt; that specify mappings
between compute source directory and VMs destination &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;mount_tags&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;share_local_fs = { "/var/lib/libvirt/scaphandre": "scaphandre" }
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the above configuration option is present starting the compute
node, add a compute trait &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SHARE_LOCAL_FS&lt;/span&gt;&lt;/code&gt; specifying the
&lt;cite&gt;virtiofs-scaphandre&lt;/cite&gt; feature is available on this compute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users can add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:power_metrics&lt;/span&gt;&lt;/code&gt; as
extra specs or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_power_metrics&lt;/span&gt;&lt;/code&gt; image properties, and thus 2 things
will happen:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Nova will schedule the instance to a host that has share_local_fs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova will add the virtiofs settings in the instance XML file as specified
by the following example.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;filesystem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'mount'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;accessmode=&lt;/span&gt;&lt;span class="s"&gt;'passthrough'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;driver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'virtiofs'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;'/var/lib/libvirt/scaphandre/&amp;lt;DOMAIN_NAME&amp;gt;'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;'mount_tag'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/filesystem&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &amp;lt;DOMAIN_NAME&amp;gt; is the name reported by &lt;cite&gt;virsh list&lt;/cite&gt;
or &lt;cite&gt;OS-EXT-SRV-ATTR:instance_name&lt;/cite&gt;.
This is the common name between qemu process that scaphandre use to get the
vm name and openstack.&lt;/p&gt;
&lt;p&gt;The instance name can be defined using the instance_name_template.
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#DEFAULT.instance_name_template"&gt;https://docs.openstack.org/nova/latest/configuration/config.html#DEFAULT.instance_name_template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;“OS-EXT-SRV-ATTR:instance_name”: “&lt;strong&gt;instance-00000034&lt;/strong&gt;”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/usr/bin/qemu-system-x86_64 -name &lt;strong&gt;guest=instance-00000034&lt;/strong&gt;…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a result, user will be able to mount the compute source directory on
his VM using the following command line.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;mount_tag&lt;span class="w"&gt; &lt;/span&gt;/var/scaphandre
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The user can see the mount_tag in the instance metadata. Mount automation
can be build based on this mechanism.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Introduce &lt;cite&gt;hw_powermetrics&lt;/cite&gt; image property as a new property object.&lt;/p&gt;
&lt;p&gt;Extend the flavor extra spec validation to check &lt;cite&gt;hw:power_metrics&lt;/cite&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The compute node filesystem will be shared read-only.
This is to prevent any modification on the host by VM users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The scaphandre installation and &lt;a class="reference external" href="https://hubblo-org.github.io/scaphandre-documentation/how-to_guides/propagate-metrics-hypervisor-to-vm_qemu-kvm.html"&gt;configuration&lt;/a&gt; on compute nodes is left
to the openstack administrator.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New configuration option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes to share the compute node filesystem if requested by an image
property or a flavor extra spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id6"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>Cleanup dangling volumes block device mapping</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/implemented/cleanup-dangling-volume-attachments.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cleanup-dangling-volume-attachments"&gt;https://blueprints.launchpad.net/nova/+spec/cleanup-dangling-volume-attachments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Find out if there are any dangling/unattached volumes in Nova and Cinder
database and remove them, if they exists.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In case after some volume related operation, volume get detached from instance
at but Nova did not get notified and thinks volume is still attached to an
instance because volume attachment id is still listed in BDM table of Nova.&lt;/p&gt;
&lt;p&gt;This can lead to different issues in functionalities, which required volume
details from block_device_mapping table, such as live miration and resizing
of instance.&lt;/p&gt;
&lt;p&gt;Similarly attachment for instance exists at Cinder side but not in Nova
DB.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want all dangling volume attachments safely removed
from my instance, as having these attachments in BDM may makes instance
goes to error state on instance startup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want all dangling volume attachments safely removed
from my instance, so any volume-related operations do not get affected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin, I want all dangling attachments listed at Cinder, safely
removed from Cinder DB that are claiming to be for the instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="notes"&gt;
&lt;h3&gt;Notes&lt;/h3&gt;
&lt;p&gt;To spawn a new instance, Nova retrieves a copy of the base OS image from
Glance, now this image is an instance storage, which means if we create any
file, it will persist in this storage. Nova creates a BDM for it in the
block_device_mapping database with source_type as image and destination_type
as local.&lt;/p&gt;
&lt;p&gt;Similarly, when we ask Nova to attach volume to an instance, Nova creates a
BDM of it in the block_device_mapping database and sets source_type and
destination_type as volume.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="changes"&gt;
&lt;h3&gt;Changes&lt;/h3&gt;
&lt;p&gt;While restarting the instance, verify, on the basis of source_type and
volume_type, whether the attached BDM is a volume or not, if it is a volume,
then verify if this volume exists in Cinder or not. If it exists, verify if
its status is “in-use” or “available”. If it’s “in-use”, that means the volume
attachment is correct, and both Nova and Cinder are aware of this attachment.
If it’s “available” that means the volume is not attached properly to the
instance, so remove or soft delete the BDM from the block_device_mapping
database.&lt;/p&gt;
&lt;p&gt;Also log the update info, so operators can be aware of the reason for this
modification in the database.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;Code Changes&lt;/h3&gt;
&lt;p&gt;To delete the BDM’s from the database, we first must need to shutdown the
instance, so instance domain get redefined at the virt level. We need to make
sure BDM’s updated before generating the new XML.&lt;/p&gt;
&lt;p&gt;Hence, this functionality should be added in the instance reboot process.
While rebooting, update the block_device_mapping DB at Nova side and
volume_attachment DB at Cinder side via Cinder API call. Once after instance
shutoff properly, while starting again, at the virt level (such as libvirt)
driver module will generate a new XML domain with updated BDM’s.&lt;/p&gt;
&lt;p&gt;Functionality _delete_dangling_bdms() should be added inside ComptuteManager
and called from ComptuteManager.reboot_instance. It should verify whether
target volume BDM source and destination type is not image and local but
volume and then if target volume is not listed in Cinder or status of volume
at Cinder is ‘available’ and not ‘in-use’ delete the BDM mapping from
block_device_mapping table.&lt;/p&gt;
&lt;p&gt;Once a dangling volume is found, log a message saying removing stale volume
attachments.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A cleanup functionality for Nova-manage utility, which takes instance
and remove all dangling volumes from instance.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova-manage&lt;span class="w"&gt; &lt;/span&gt;volume_attachment&lt;span class="w"&gt; &lt;/span&gt;cleanup&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;server-id&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A cron job which check for each instance in the Nova BDM and Cinder
volume_attachment table, if instance has dangling volumes, remove volume
entry from table. In this job instance UUID is not required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Server might take more time to reboot, as there will be GET and DELETE
API call(s) towards Cinder service.&lt;/p&gt;
&lt;p&gt;It primarily depends on number of attachments to delete.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;auniyal&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a cleanup functionality and add in instance restart process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit and functional tests for cleanup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and Functional tests will be added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Releasenote for cleanup dangling volumes while server restart will be added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update admin manage volumes doc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>Link Compute Objects by ID</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/implemented/compute-object-ids.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/compute-object-ids"&gt;https://blueprints.launchpad.net/nova/+spec/compute-object-ids&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova has long had a dependency on an unchanging hostname on the
compute nodes. This spec aims to address this limitation, at least
from the perspective of being able to detect an accidental change and
avoiding catastrophe in the database that can currently result from a
hostname change, whether intentional or not.&lt;/p&gt;
&lt;p&gt;As a continuation of the effort to &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/backlog/approved/robustify-compute-hostnames.html"&gt;robustify compute hostnames&lt;/a&gt;, this spec
describes the next phase which involves strengthening the linkage between the
primary database objects managed by the compute nodes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Service&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; objects form the primary
data model for our compute nodes. Instances run on compute nodes, which are
managed by services. We rely on this hierarchy to know where instances are
(physically) as well as which RPC endpoint to send messages to for management.
Currently, the linkage between all three objects is a relatively loose and
string-based, association using the hostname of the compute node and/or the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.host&lt;/span&gt;&lt;/code&gt; values. This not only makes an actual/intentional rename very
difficult, but also risks breaking critical links as a result of an
&lt;em&gt;accidental&lt;/em&gt; one.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I want an accidental or transient hostname rename to not cause
corruption of my Nova data structures.&lt;/p&gt;
&lt;p&gt;As a developer, I want a stronger association between the primary objects in
the data model for robustness and performance reasons.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We already have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service_id&lt;/span&gt;&lt;/code&gt; field on our &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt; object. We should
resume populating that when we create a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt; and we should fix
existing records during &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeManager.init_host()&lt;/span&gt;&lt;/code&gt;, similar to how we added
checks for hostname discrepancies in the earlier phase of this effort.&lt;/p&gt;
&lt;p&gt;We will need to add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_id&lt;/span&gt;&lt;/code&gt; field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; object, which
will require a schema migration. This field will need to remain nullable, and
will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NULL&lt;/span&gt;&lt;/code&gt; for instances before scheduling, as well as instances in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED_OFFLOADED&lt;/span&gt;&lt;/code&gt; state. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_id&lt;/span&gt;&lt;/code&gt; field can be populated at the
same time we currently set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.node&lt;/span&gt;&lt;/code&gt;, and similar to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt;
records above, we can migrate existing records during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeManager._init_instance()&lt;/span&gt;&lt;/code&gt;. In order to ensure that we keep the &lt;cite&gt;node&lt;/cite&gt;
and &lt;cite&gt;compute_id&lt;/cite&gt; fields in sync, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.create()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.update()&lt;/span&gt;&lt;/code&gt; methods will perform a check to ensure that the former is
never changed without the latter also being changed. This check will (by the
nature of those two &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@remotable&lt;/span&gt;&lt;/code&gt; methods) be run on the conductor nodes, and
will only enforce the requirement if the version of the objects is new enough.&lt;/p&gt;
&lt;p&gt;Many of the times we update &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.node&lt;/span&gt;&lt;/code&gt;, we do so from a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt;
object, using either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;source_node&lt;/span&gt;&lt;/code&gt; for reverted migrations or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dest_node&lt;/span&gt;&lt;/code&gt;
for successful ones. Thus, our handling of migrations will need some work as
well, which is described in the subsection below.&lt;/p&gt;
&lt;p&gt;It is important to note that this spec defines one part of a two-part effort.
The setup described here will require a subsequent step to change how we
look up these objects to use the new relationships once all the data has been
migrated.&lt;/p&gt;
&lt;section id="migration-handling"&gt;
&lt;h3&gt;Migration handling&lt;/h3&gt;
&lt;p&gt;Currently we update &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.node&lt;/span&gt;&lt;/code&gt; from a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; object in a number
of places. In most of these, it is being performed &lt;em&gt;on&lt;/em&gt; the node where the
instance will remain. For those cases, we will get the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt; object
from the resource tracker (still by name, from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; object) and
use it to set the new field. Aside from saving a loosely-coupled DB lookup
each time we need it, this has the additional benefit of double-checking that
the node specified (loosely, by name) in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; object is the (or a)
correct one for the current host.&lt;/p&gt;
&lt;p&gt;The only place where we currently update &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.node&lt;/span&gt;&lt;/code&gt; from a location that
is &lt;em&gt;not&lt;/em&gt; the host where the Instance is staying is during the early part of
resize, where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_resize_instance()&lt;/span&gt;&lt;/code&gt; runs on the sending host with information
provided by the destination. In this case, we will modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt;
object to have one additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dest_compute_id&lt;/span&gt;&lt;/code&gt; field, which will be filled
by the destination host with its known-correct value, to be used by the sending
host when it modifies &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.node&lt;/span&gt;&lt;/code&gt; (and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.compute_id&lt;/span&gt;&lt;/code&gt;) to be the
values for the new host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-concerns"&gt;
&lt;h3&gt;Upgrade Concerns&lt;/h3&gt;
&lt;p&gt;Since the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; objects will be growing new fields,
older nodes will not be populating these fields when migrating between old and
new nodes. In the case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt;, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_id&lt;/span&gt;&lt;/code&gt; field will not be
actually used until a later release when we know it has been populated. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dest_compute_id&lt;/span&gt;&lt;/code&gt; field in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; will be used if present, and if not,
a fallback to finding the node’s ID will rely on a call to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode.get_by_host_and_nodename()&lt;/span&gt;&lt;/code&gt;, which is “easy” since the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; has all the fields necessary to make that call.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This is not &lt;em&gt;required&lt;/em&gt; for proper operation, so we could choose to do nothing.&lt;/p&gt;
&lt;p&gt;We could also choose to keep the string-based association, strengthened by
Foreign Key relationships.&lt;/p&gt;
&lt;p&gt;For the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; changes, we could also make the destination compute ID
be a new RPC parameter that is passed from the destination compute back to the
source to avoid needing to change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; object. However that
brings with it more upgrade concerns.&lt;/p&gt;
&lt;p&gt;We could also use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode.uuid&lt;/span&gt;&lt;/code&gt; on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration&lt;/span&gt;&lt;/code&gt; object instead
of the ID. There is no real reason to do that because cross-cell migration
already creates two migration objects, one per cell. It would also perform
worse and would not be a 1:1 mapping of the field we need to set on the
instance, which would mean another DB lookup as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;All changes will be confined to the Cell database:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance will grow a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_id&lt;/span&gt;&lt;/code&gt; field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migration will grow a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dest_compute_id&lt;/span&gt;&lt;/code&gt; field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistency checks for both of these will need to be added to the object
lifecycle operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ComputeNode’s existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service_id&lt;/span&gt;&lt;/code&gt; field will be populated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both will be populated during new record creation, and for existing records
at runtime during &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; startup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;While not the primary intent, a follow-on effort to this will enable querying
these objects by integer ID relation instead of by string, which should be
both faster as well as lower impact on the database server.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;No additional deployer impact other than a tiny amount of online data
migration traffic on the next startup after upgrade, as well as improved
performance and robustness going forward once the effort is completed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Some additional re-learning about the relationships between the objects being
based on IDs instead of hostnames.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;No real upgrade impact here, other than what is already expected. A simple and
database migration will be added, with no specific requirements about ordering
or simultaneous code change. Compute nodes will migrate existing records during
the first post-upgrade restart.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Start populating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode.service_id&lt;/span&gt;&lt;/code&gt; on creation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrate existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt; objects on startup (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;init_host()&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a migration to add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.compute_id&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.dest_compute_id&lt;/span&gt;&lt;/code&gt; fields&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start populating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.dest_compute_id&lt;/span&gt;&lt;/code&gt; for migrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start populating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance.compute_id&lt;/span&gt;&lt;/code&gt; on completion of scheduling and
migrations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrate existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; objects on startup (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_init_instance()&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and Functional tests will be added to verify that new and existing objects
are properly linked and migrated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;No documentation changes required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This is part of a larger multi-cycle effort to
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/backlog/approved/robustify-compute-hostnames.html"&gt;robustify compute hostnames&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This follows the &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/stable-compute-uuid.html"&gt;first robustification stage&lt;/a&gt;, completed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;2023.1&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>Add maxphysaddr support for Libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/implemented/libvirt-maxphysaddr-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-maxphysaddr-support"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-maxphysaddr-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint propose new flavor extra_specs to control the physical
address bits of vCPUs in Libvirt guests.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When booting a guest with 1TB+ RAM, the default physical address bits are
too small and the boot fails &lt;a class="footnote-reference brackets" href="#id9" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. So a knob is needed to specify the
appropriate physical address bits.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Booting a guest with large RAM.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In Libvirt v8.7.0+ and QEMU v2.7.0+, physical address bits can be specified
with following XML elements &lt;a class="footnote-reference brackets" href="#id10" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id11" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. The former means to adopt any physical
address bits, the latter means to adopt the physical address bits of the
host CPU.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;maxphysaddr&lt;/span&gt; &lt;span class="pre"&gt;mode='emulate'&lt;/span&gt; &lt;span class="pre"&gt;bits='42'/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;maxphysaddr&lt;/span&gt; &lt;span class="pre"&gt;mode='passthrough'/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="flavor-extra-specs"&gt;
&lt;h3&gt;Flavor extra_specs&lt;/h3&gt;
&lt;p&gt;Here I suggest the following two flavor extra_specs.
Of course, if these are omitted, the behavior is the same as before.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode&lt;/span&gt;&lt;/code&gt; can be either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;emulate&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passthrough&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt; takes a positive integer value.
Only meaningful and must be specified if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="nova-scheduler-changes"&gt;
&lt;h3&gt;Nova scheduler changes&lt;/h3&gt;
&lt;p&gt;Nova scheduler also needs to be modified to take these two properties
into account.&lt;/p&gt;
&lt;p&gt;There can be a mix of supported and unsupported hosts depending
on Libvirt and QEMU versions. So add new traits
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_PASSTHROUGH&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt;
to check the scheduled host supports this feature.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_ADDRESS_SPACE_PASSTHROUGH=required&lt;/span&gt;&lt;/code&gt; is automatically added
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; is specified in flavor extra_specs.
And same for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Passthrough and emulate modes have different properties. So let’s consider
the two separately.&lt;/p&gt;
&lt;p&gt;The case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt;. In this case,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt; is a requirement, which is already taken
into account in nova scheduling, and no additional modifications are
required in this proposal. It is not guaranteed whether the instance
can be migrated by nova. So the admin needs to make sure that targets
of cold and live migration have similar hardware and software.
This restriction is similar for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. In nova scheduling,
it is necessary to check that the hypervisor supports at least
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt;. The maximum number of bits supported by
hypervisor can be obtained by using libvirt capabilities &lt;a class="footnote-reference brackets" href="#id12" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Therefore,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; can be used to compare the number of bits in
scheduling.  For example, this can be accomplished by adding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;capabilities:cpu_info:maxphysaddr:bits&amp;gt;=42&lt;/span&gt;&lt;/code&gt; automatically.
Cold migration and live migration can also be realized with this filter
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt; trait.
So the overall flavor extra_specs look like the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maxphysaddr_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;emulate&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maxphysaddr_bits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since ComputeCapabilitiesFilter only supports flavor extra_specs
and not image properties &lt;a class="footnote-reference brackets" href="#id13" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, this proposal is out of scope for
image properties.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Before the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxphysaddr&lt;/span&gt;&lt;/code&gt; option was introduced into Libvirt, it was specified
as a workaround with the QEMU comanndline parameter. But this alternative is
not allowed in nova.&lt;/p&gt;
&lt;p&gt;Also, some Linux distributions may have machine types with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host-phys-bits=true&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id14" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. For example, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc-i440fx-bionic-hpb&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc-q35-bionic-hpb&lt;/span&gt;&lt;/code&gt;. However, this alternative has following two issues and
cannot be adopted for general-purpose use cases.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ubuntu package maintainers are applying a patch to QEMU &lt;a class="footnote-reference brackets" href="#id15" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. It means this
is not included in vanilla QEMU and is not available in other distributions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is only the case for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; and does not
include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. Since
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; requires &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt;
to be used &lt;a class="footnote-reference brackets" href="#id16" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, this alternative cannot be used with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=custom&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-model&lt;/span&gt;&lt;/code&gt;. So, this alternative is not sufficient for
a cloud with many different CPU models.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As for scheduling, placement does not currently support numeric traits,
so the maximum number of bits supported by hypervisor cannot be checked
by this mechanism.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators should specify appropriate flavor extra_specs as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As described earlier, the new traits &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_PASSTHROUGH&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt; signal if the upgraded compute nodes support
this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nmiki&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new guest configs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fileds in nova/api/validation/extra_specs/hw.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fields in LibvirtConfigCPU in nova/virt/livbirt/config.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new traits to check Libvirt and QEMU versions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxphysaddr&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info&lt;/span&gt;&lt;/code&gt; in nova/virt/libvirt/driver.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs and release notes for new flavor extra_specs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Libivrt v8.7.0+.
QEMU v2.7.0+.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add the following unit tests:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;check that proposed flavor extra_specs are properly validated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that intended XML elements are output&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that traits are properly added and used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that new field in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; is property
added and used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;For operators, the documentation describes what proposed flavor extra_specs
mean and how they should be set.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1769053"&gt;https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1769053&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/news.html#v8-7-0-2022-09-01"&gt;https://libvirt.org/news.html#v8-7-0-2022-09-01&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/commit/1c1a7cdd4096c59fb0c374529e1e5aea8d43ee9c"&gt;https://github.com/libvirt/libvirt/commit/1c1a7cdd4096c59fb0c374529e1e5aea8d43ee9c&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatcaps.html#examples"&gt;https://libvirt.org/formatcaps.html#examples&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/scheduling.html#computecapabilitiesfilter"&gt;https://docs.openstack.org/nova/latest/admin/scheduling.html#computecapabilitiesfilter&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id14" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://cpaelzer.github.io/blogs/005-guests-bigger-than-1tb/"&gt;https://cpaelzer.github.io/blogs/005-guests-bigger-than-1tb/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/commit/?id=6ba8b5c843d405e1b067dc8b98ecb8545af78a2b"&gt;https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/commit/?id=6ba8b5c843d405e1b067dc8b98ecb8545af78a2b&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/blob/v8.7.0/src/qemu/qemu_validate.c#L346-L351"&gt;https://github.com/libvirt/libvirt/blob/v8.7.0/src/qemu/qemu_validate.c#L346-L351&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id17"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>Tooling and Docs for Unified Limits</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/implemented/unified-limits-nova-tool-and-docs.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unified-limits-nova-tool-and-docs"&gt;https://blueprints.launchpad.net/nova/+spec/unified-limits-nova-tool-and-docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the Yoga release support for Unified Limits was added in Nova as an
experimental feature to get early feedback and fix issues that were found by
operators trying it out. Now that a few releases have passed, we want to go
ahead and formalize the unified limits quota driver by creating a tool to help
operators copy their existing legacy quota limits from Nova to unified limits
in Keystone, publish official documentation in the Nova quota documentation,
and removing the note on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;
config option indicating its experimental status.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;There are no immediate plans to deprecate legacy quota system in Nova at
this time. The objective of this work is to provide a better experience for
users who are opting in to using unified limits in Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there is no documentation in the Nova docs about unified limits and
there isn’t any automated tool for generating unified limits in Keystone from
existing Nova legacy quota limits.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I would like to use a tool to automatically copy my existing
legacy quota limits from Nova to unified limits in Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I would like formal documentation for unified limits quotas
to be available.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose to create an automated tool, for example,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt; &lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt; that will read existing legacy
quota limits from the Nova database and config options and create equivalent
unified limits for them in Keystone using the Keystone REST API. It will be
able to migrate both default limits and project-scoped limits. It will not
migrate user-scoped limits as they are not supported by unified limits.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will follow the precedence for &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/quotas.html#checking-quota"&gt;checking quota&lt;/a&gt;
and:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Check the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.quotas&lt;/span&gt;&lt;/code&gt; database table and for each row call the
Keystone &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; API with the project_id, resource name, and
resource_limit. These are the project-scoped limits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.quota_classes&lt;/span&gt;&lt;/code&gt; database table to see if there are rows
with class_name &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default&lt;/span&gt;&lt;/code&gt;. If there are, for each row with class_name
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default&lt;/span&gt;&lt;/code&gt; call the Keystone &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/registered_limits&lt;/span&gt;&lt;/code&gt; API with the
resource_name and default_limit. These are the default limits that apply to
all projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the following config options:&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[quota]&lt;/span&gt;
&lt;span class="na"&gt;instances&lt;/span&gt;
&lt;span class="na"&gt;cores&lt;/span&gt;
&lt;span class="na"&gt;ram&lt;/span&gt;
&lt;span class="na"&gt;metadata_items&lt;/span&gt;
&lt;span class="na"&gt;injected_files&lt;/span&gt;
&lt;span class="na"&gt;injected_file_content_bytes&lt;/span&gt;
&lt;span class="na"&gt;injected_file_path_length&lt;/span&gt;
&lt;span class="na"&gt;key_pairs&lt;/span&gt;
&lt;span class="na"&gt;server_groups&lt;/span&gt;
&lt;span class="na"&gt;server_group_members&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For each config option, use its set value or default value to call the
Keystone &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/registered_limits&lt;/span&gt;&lt;/code&gt; API with the resource_name and
default_limit, if the resource_name does not already have a registered limit
in Keystone. These are default limits that apply to all projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.project_user_quotas&lt;/span&gt;&lt;/code&gt; database table will be ignored because
user-scoped limits are not supported by unified limits.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will add formal docs about unified limits to the Nova docs and remove the
note on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt;&lt;/code&gt; config option about the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; being in a development state.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Operators can create unified limits using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;limit&lt;/span&gt;&lt;/code&gt; openstack
client commands without a provided tool.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;End users will be able to read documentation about how quotas work with unified
limits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will have the option of using the quota limit migration tool to copy
existing legacy Nova quota limits into Keystone unified limits instead of using
openstackclient commands or otherwise calling the Keystone REST API manually.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;There is no upgrade impact with the quota limit migrate tool in that there is
no restriction on when operators can run the tool. They can copy quota limits
into Keystone at any time, unrelated to an upgrade. The only requirements are
that the Keystone API needs to be available and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; must have
access to a Nova config that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api_database]connection&lt;/span&gt;&lt;/code&gt; configured so
that it can access the Nova quota database tables.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Develop a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;limits&lt;/span&gt; &lt;span class="pre"&gt;migrate_to_unified_limits&lt;/span&gt;&lt;/code&gt; command to copy
existing legacy Nova quota limits from the Nova database and config options
to unified limits by calling the Keystone REST API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write documentation for unified limits in Nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove note from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; about the
driver being in a development state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collaborate with Keystone team to remove the docs warning in
&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/admin/unified-limits.html"&gt;https://docs.openstack.org/keystone/latest/admin/unified-limits.html&lt;/a&gt;
about the unified limits API labeled as experimental&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and/or functional testing for the quota limit migrate tool wil be added.&lt;/p&gt;
&lt;p&gt;We can also test the quota limit migrate tool alongside the existing
nova/tools/hooks/post_test_hook.sh unified limits coverage in the nova-next CI
job.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operators will be most affected by the addition of Nova unified limits
documentation. The following docs will need to be updated:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/quotas.html"&gt;https://docs.openstack.org/nova/latest/user/quotas.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/quotas.html"&gt;https://docs.openstack.org/nova/latest/admin/quotas.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html"&gt;https://docs.openstack.org/nova/latest/cli/nova-manage.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-bobcat-ptg#L415"&gt;https://etherpad.opendev.org/p/nova-bobcat-ptg#L415&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/admin/unified-limits.html"&gt;https://docs.openstack.org/keystone/latest/admin/unified-limits.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Sep 2023 00:00:00 </pubDate></item><item><title>Use extend volume completion action</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/approved/assisted-volume-extend.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend"&gt;https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume
action that has been proposed for Cinder in &lt;a class="footnote-reference brackets" href="#id12" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, to provide feedback on
success or failure when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server events.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many remotefs-based volume drivers in Cinder use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;resize&lt;/span&gt;&lt;/code&gt;
command to extend volume files.
However, when the volume is attached to a guest, QEMU will lock the file and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt;&lt;/code&gt; will be unable to resize it.&lt;/p&gt;
&lt;p&gt;In this case, only the QEMU process holding the lock can resize the volume,
which can be triggered through the QEMU monitor command &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is currently no adequate way for Cinder to use this feature, so the NFS,
NetApp NFS, Powerstore NFS, and Quobyte volume drivers all disable extending
attached volumes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I want to extend a NFS/NetApp NFS/Powerstore NFS/Quobyte volume
while it is attached to an instance and I want the volume size and status to
reflect the success or failure of the operation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova’s libvirt driver uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command when handling the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event, to inform QEMU that the size of an
attached volume has changed.
It is in principle also capable of extending a volume file, but is currently
unable to provide feedback to Cinder on the success of the operation.&lt;/p&gt;
&lt;p&gt;Currently, Cinder will send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event to
Nova only after it has finalized the extend operation and reset the volume
status from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;a class="footnote-reference brackets" href="#id12" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, Cinder will allow volume drivers to hold off finalizing the extend
operation and leave the volume status as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, until after it has
send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event and received feedback from Nova in form of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action, with an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; argument
indicating whether to finalize or to roll back the operation.&lt;/p&gt;
&lt;p&gt;This will currently affect only the volume drivers mentioned above, all of
which did not previously support online extend.
All other drivers will continue to send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event after
finalizing the operation and resetting to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt; status, and will not
expect a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action.&lt;/p&gt;
&lt;section id="compute-agent"&gt;
&lt;h3&gt;Compute Agent&lt;/h3&gt;
&lt;p&gt;Nova’s compute agent will use the volume status to differentiate between the
two behaviors when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the volume status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, then it will attempt to read
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; from the volume’s metadata and use this value as the
new size of the volume, instead of the volume size field.&lt;/p&gt;
&lt;p&gt;After successfully extending the volume, it will call the extend volume
completion action of the volume, with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;false&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If anything goes wrong, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; being missing from the
metadata, or being smaller than the current size of the volume, it will
log the error and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;, so Cinder can roll back the operation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For any other volume status, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, the event will be handled
as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="api"&gt;
&lt;h3&gt;API&lt;/h3&gt;
&lt;p&gt;Nova’s API will introduce a new microversion, so that Cinder can make sure the
new behavior is available, before leaving an extend operation unfinished.&lt;/p&gt;
&lt;p&gt;To handle older compute agents during a rolling upgrade, the API will also
check the compute service version of the target agent when receiving a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event with the new microversion.
If a target compute agent is too old to support the feature, the API will
discard the event and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A previous change tried to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event
to support online extend for the NFS driver &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but did not rely on
feedback from Nova to Cinder at all.
Instead, it would just set the new size of the volume, change the status
back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, notify Nova, and hope for the best.&lt;/p&gt;
&lt;p&gt;If anything went wrong on Nova’s side, this would still result in a volume
state indicating that the operation was successful, which is not acceptable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A previous version of this spec proposed a new synchronous API in Nova &lt;a class="footnote-reference brackets" href="#id11" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;,
that would directly call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CompVirtAPI.extend_image&lt;/span&gt;&lt;/code&gt; of the nova-compute
instance managing the guest that a volume was attached to.
This API would provide a single mechanism to trigger the resize operation,
communicate the new size to Nova, and get feedback on the success of the
operation.&lt;/p&gt;
&lt;p&gt;The problem with a synchronous API is, that RPC and API timeouts limit the
maximum time an extend operation can take.
For QEMU, this seemed to be acceptable, because storage preallocation is
hard disabled for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command, and because all currently
plausible file systems support sparse file operations.&lt;/p&gt;
&lt;p&gt;However, this may not be true for other volume or virt drivers that might
require this API in the future.
It would also break with the established pattern of asynchronous
coordination between Nova and Cinder, which includes the assisted snapshot
and volume migration features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Following this pattern, we could make the proposed API asynchronous and use
a new callback in Cinder, similar to Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-assisted-volume-snapshots&lt;/span&gt;&lt;/code&gt;
API, which uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-update_snapshot_status&lt;/span&gt;&lt;/code&gt; snapshot action to provide
feedback to Cinder.&lt;/p&gt;
&lt;p&gt;The function of the new Nova API would then just be to trigger the operation
and to communicate the new size.
The question is then, whether that warrants adding a new API to Nova, since
there are existing mechanisms that could be used for either.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The existing mechanism for triggering the extend operation in Nova is of
course the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event.
Using it for this purpose, as this spec proposes, requires the target size
to be transferred separately, because external server events only have a
single text field that is freely usable, which for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt;
is already used for the volume ID.&lt;/p&gt;
&lt;p&gt;Besides storing it in the admin metadata, as &lt;a class="footnote-reference brackets" href="#id12" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and this spec propose,
there is also the option of updating the size field of the volume, as &lt;a class="footnote-reference brackets" href="#id10" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
was essentially doing.&lt;/p&gt;
&lt;p&gt;This would require the volume size field to be reset on a failure.
If an error response from Nova was lost, the volume would just keep the new
size.
We would need to extend &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-reset_status&lt;/span&gt;&lt;/code&gt; to allow a size reset, or
something similar to clean up volumes like this.
This would be possible, but updating the size field only after the volume
was successfully extended seems like a cleaner solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could also extend the external server event API to accept additional data
for events, and use this to communicate the new size to Nova.&lt;/p&gt;
&lt;p&gt;This option was judged favorably by reviewers on the previous version of
this spec, &lt;a class="footnote-reference brackets" href="#id11" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but it would be a more complex change to the Nova API.&lt;/p&gt;
&lt;p&gt;However, if additional data fields become available in a future version of
the external server event API, it would be a relatively minor change to use
this instead of volume metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The behavior of the external server event API will change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If Nova receives a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event, and the referenced volume has
status of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, Nova will look for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; key in
the volume metadata, and use this instead of the volume size field as the
target size to update the block device mapping and to pass to the virt
driver’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_volume&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Nova will also attempt to call Cinder’s new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt;
volume action proposed in &lt;a class="footnote-reference brackets" href="#id12" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to let Cinder know if the operation was
successful or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, the API will behave as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Checking the target compute service version allows the API to handle rolling
upgrades gracefully.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kgube&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None yet&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the external server event API to check the target compute service
version for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeVirtAPI.extend_volume&lt;/span&gt;&lt;/code&gt; method to follow the behavior
outlined in &lt;a class="reference internal" href="#compute-agent"&gt;Compute Agent&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt NFS job in the Nova gate to validate online extend.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The extend volume completion action &lt;a class="footnote-reference brackets" href="#id12" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We should test that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; gets called correctly
in all possible error or success condition if a volume has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;
status.&lt;/p&gt;
&lt;p&gt;We should test the case that the call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; fails.&lt;/p&gt;
&lt;p&gt;We also need to test that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; continues to be handled correctly
for volumes not in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; status.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new behavior of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event should be added to the
documentation of the external server event API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/739079"&gt;https://review.opendev.org/c/openstack/cinder/+/739079&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id4"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/855490/6"&gt;https://review.opendev.org/c/openstack/nova-specs/+/855490/6&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id9"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder-specs/+/877230"&gt;https://review.opendev.org/c/openstack/cinder-specs/+/877230&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id13"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 18 Sep 2023 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2024.1/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2024.1 Caracal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 21 Jul 2023 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will only cover the high level changes to the API and compute
layers, implementation within specific virt drivers is left for separate
specs.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To enable snapshot and shelve of instances using ephemeral encryption, the UUID
of the encryption secret is stored in the key manager for the resultant image
will be kept with the image as an image property:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The secret UUID is needed when creating an instance from an ephemeral encrypted
snapshot or when unshelving an ephemeral encrypted instance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="create-a-new-key-manager-secret-for-every-new-encrypted-disk-image"&gt;
&lt;h3&gt;Create a new key manager secret for every new encrypted disk image&lt;/h3&gt;
&lt;p&gt;The approach for disk image secrets is to never share secrets between different
disk images and that each disk image has a unique secret. This is done to
address both 1) the security implications and 2) the logistics of cleaning up
secrets that are no longer in use.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;Let’s say &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt; &lt;span class="pre"&gt;A&lt;/span&gt;&lt;/code&gt; has 3 disks: one root disk, one ephemeral disk, and
one swap disk. Each disk will have its own secret.&lt;/p&gt;
&lt;p&gt;This table is intended to illustrate the way secrets are handled in various
scenarios.&lt;/p&gt;
&lt;div class="highlight-rst notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Instance or Image  | Disk        | Secret       | Notes                                                |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             | (passphrase) |                                                      |
+====================+=============+==============+======================================================+
&lt;span class="o"&gt;|&lt;/span&gt; Instance A         | disk (root) | Secret 1     | Secret 1, 2, and 3 will be automatically deleted     |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+ by Nova when Instance A is deleted and its disks are |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.eph0   | Secret 2     | destroyed                                            |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+                                                      |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.swap   | Secret 3     |                                                      |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Image Z (snapshot) | disk (root) | Secret 4     | Secret 4 will &lt;span class="ge"&gt;*not*&lt;/span&gt; be automatically deleted and     |
&lt;span class="o"&gt;|&lt;/span&gt; created from       |             | (new secret  | manual deletion will be needed if/when Image Z is    |
&lt;span class="o"&gt;|&lt;/span&gt; Instance A         |             |  is created) | deleted from Glance                                  |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Instance B         | disk (root) | Secret 5     | Secret 5, 6, and 7 will be automatically deleted     |
&lt;span class="o"&gt;|&lt;/span&gt; created from       +-------------+--------------+ by Nova when Instance B is deleted and its disks are |
&lt;span class="o"&gt;|&lt;/span&gt; Image Z (snapshot) | disk.eph0   | Secret 6     | destroyed                                            |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+                                                      |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.swap   | Secret 7     |                                                      |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Instance C         | disk (root) | Secret 8     | Secret 8, 9, and 10 will be automatically deleted    |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+ by Nova when Instance C is deleted and its disks are |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.eph0   | Secret 9     | destroyed                                            |
&lt;span class="o"&gt;|&lt;/span&gt;                    +-------------+--------------+                                                      |
&lt;span class="o"&gt;|&lt;/span&gt;                    | disk.swap   | Secret 10    |                                                      |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Image Y (snapshot) | disk (root) | Secret 8     | Secret 8 is &lt;span class="ge"&gt;*retained*&lt;/span&gt; when Instance C is shelved in |
&lt;span class="o"&gt;|&lt;/span&gt; created by shelve  |             |              | part to prevent the possibility of a change in       |
&lt;span class="o"&gt;|&lt;/span&gt; of Instance C      |             |              | ownership of the root disk secret if, for example,   |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | an admin user shelves a non-admin user's instance.   |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | This approach could be avoided if there is some way  |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | we could create a new secret using the instance's    |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | user/project rather than the shelver's user/project  |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;span class="o"&gt;|&lt;/span&gt; Rescue disk        | disk (root) | Secret 11    | Secret 11 is stashed in the instance's system        |
&lt;span class="o"&gt;|&lt;/span&gt; created by rescue  |             | (new secret  | metadata with key                                    |
&lt;span class="o"&gt;|&lt;/span&gt; of Instance A      |             |  is created) | &lt;span class="s"&gt;``rescue_disk_ephemeral_encryption_secret_uuid``&lt;/span&gt;.    |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | This is done because a BDM record for the rescue     |
&lt;span class="o"&gt;|&lt;/span&gt;                    |             |              | disk is not going to be persisted to the database.   |
+--------------------+-------------+--------------+------------------------------------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="snapshots-of-instances-with-ephemeral-encryption"&gt;
&lt;h4&gt;Snapshots of instances with ephemeral encryption&lt;/h4&gt;
&lt;p&gt;When an instance with ephemeral encryption is snapshotted, a new encryption
secret is created and its key manager secret UUID is kept as an image property
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; and the image is uploaded to Glance.&lt;/p&gt;
&lt;p&gt;When a new instance is created from an encrypted image, the image property
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; is passed down to the lower layers by
storing it in the instance’s system metadata with key
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;. This is done because at the
lower layers (where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;convert&lt;/span&gt;&lt;/code&gt; is called, for example) we no longer
have access to the image metadata and refactoring to pass image metadata to
several lower layer methods, or similar, would be required otherwise.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="snapshots-created-by-shelving-instances-with-ephemeral-encryption"&gt;
&lt;h4&gt;Snapshots created by shelving instances with ephemeral encryption&lt;/h4&gt;
&lt;p&gt;When an instance with ephemeral encryption is shelved, the existing root disk
encryption secret is &lt;em&gt;retained&lt;/em&gt; and will be used to unshelve the instance
later. This is done to prevent a potential change in ownership of the root disk
encryption secret in a scenario where an admin user shelves a non-admin user’s
instance, for example. If a new secret were created owned by the admin user,
the non-admin user who owns the instance will be unable to unshelve the
instance.&lt;/p&gt;
&lt;p&gt;This behavior could be avoided however if there is some way we could create a
new encryption secret using the instance’s user and project rather than the
shelver’s user and project. If that is possible, we would not need to reuse the
encryption secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rescue-disk-images-created-by-rescuing-instances-with-ephemeral-encryption"&gt;
&lt;h4&gt;Rescue disk images created by rescuing instances with ephemeral encryption&lt;/h4&gt;
&lt;p&gt;When rescuing an instance and an encrypted rescue image is
specified, the rescue image secret UUID from the image property will be stashed
in the instance’s system metadata with key
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rescue_image_hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; to pass it down to the
lower layers. This is considered separate from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_hw_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt; which means the encrypted image
from which the instance was created. Another reason to keep it separate is to
avoid confusion for those reading or working on the code.&lt;/p&gt;
&lt;p&gt;A new encryption secret is created when the rescue disk is created and its UUID
is stashed in the instance’s system metadata with key
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rescue_disk_ephemeral_encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;. This is done because a block
device mapping record for the rescue disk is not going to be persisted to the
database.&lt;/p&gt;
&lt;p&gt;The corresponding virt driver secret name pattern is
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;instance&lt;/span&gt; &lt;span class="pre"&gt;UUID&amp;gt;_rescue_disk&lt;/span&gt;&lt;/code&gt; and any existing secrets with that name are
deleted by the virt driver when a new rescue is requested.&lt;/p&gt;
&lt;p&gt;The new encryption secret for the rescue disk is deleted from the key manager
and the virt driver secret is also deleted when the instance is unrescued.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="cleanup-of-ephemeral-encryption-secrets"&gt;
&lt;h4&gt;Cleanup of ephemeral encryption secrets&lt;/h4&gt;
&lt;p&gt;Ephemeral encryption secrets are deleted from the key manager and the virt
driver when the corresponding instance is deleted and its disks are destroyed.
The approach is that encryption secrets are &lt;em&gt;only&lt;/em&gt; deleted when the disks
associated with them are destroyed.&lt;/p&gt;
&lt;p&gt;Encryption secrets that are created when a snapshot is created are &lt;em&gt;never&lt;/em&gt;
deleted by Nova. It would only be acceptable to delete the secret if and when
the snapshot image is deleted. Cleanup of secrets whose images have been
deleted from Glance must be deleted manually by the user or an admin.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;At the time of this writing, the newest Ceph release v17 (Quincy) does not
support creating a cloned image with an encryption key different from its
parent. For this reason, copy-on-write cloning will not be enabled for
instances which have specified ephemeral encryption.&lt;/p&gt;
&lt;p&gt;Support for creating a cloned image with an encryption key different from
its parent should be supported in the next release of Ceph.
When we are able to require a Ceph version &amp;gt;= v18, copy-on-write cloning
with ephemeral encryption can be enabled.
See &lt;a class="reference external" href="https://github.com/ceph/ceph/commit/1d3de19"&gt;https://github.com/ceph/ceph/commit/1d3de19&lt;/a&gt; for reference.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; field will be unused and not exposed to end
users initially because of the security and upgrade implications around it.
For the first pass, sensible defaults for the cipher algorithm, cipher
mode, and initialization vector generator algorithm will be hard-coded
instead.&lt;/p&gt;
&lt;p&gt;Encryption options could be exposed to end users in the future when a
proper design which addresses security and handles all upgrade scenarios is
developed.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility trait was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Internal base images stored locally in Nova will not be encrypted at rest.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Jul 2023 00:00:00 </pubDate></item><item><title>Handling Reshaped Provider Trees</title><link>https://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/reshape-provider-tree.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/reshape-provider-tree"&gt;https://blueprints.launchpad.net/nova/+spec/reshape-provider-tree&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Virt drivers need to be able to change the structure of the provider trees they
expose. When moving existing resources, existing allocations need to be moved
along with the inventories. And this must be done in such a way as to avoid
races where a second entity can create or remove allocations against the moving
inventories.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The libvirt driver currently inventories VGPU resources on the compute node
provider. In order to exploit provider trees, libvirt needs to create one
child provider per physical GPU and move the VGPU inventory from the compute
node provider to these GPU child providers. In a live deployment where VGPU
resources are already allocated to instances, the allocations need to be
moved along with the inventories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drivers wishing to model NUMA must similarly create child providers and move
inventory and allocations of several classes (processor, memory, VFs on
NUMA-affined NICs, etc.) to those providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A driver is using a custom resource class. That resource class is added to
the standard set (under a new, non-&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_&lt;/span&gt;&lt;/code&gt; name). In order to use the
standard name, the driver must move inventory and allocations from the old
name to the new.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are just example cases that may exist now or in the future.  We’re
describing a generic pivot system here.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The overall flow is as follows. The parts in red only happen when a reshape is
needed. This represents the happy path on compute startup only.&lt;/p&gt;
&lt;img alt="../../../_images/reshape-provider-tree.svg" src="../../../_images/reshape-provider-tree.svg"/&gt;
&lt;p&gt;Note that, for Fast-Forward Upgrades, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Resource&lt;/span&gt; &lt;span class="pre"&gt;Tracker&lt;/span&gt;&lt;/code&gt; lane is actually
the &lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt;.&lt;/p&gt;
&lt;section id="schedulerreportclient-get-allocations-for-provider-tree"&gt;
&lt;span id="get-allocations-for-provider-tree"/&gt;&lt;h3&gt;SchedulerReportClient.get_allocations_for_provider_tree()&lt;/h3&gt;
&lt;p&gt;A new SchedulerReportClient method shall be implemented:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get_allocations_for_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Retrieve allocation records associated with all providers in the&lt;/span&gt;
&lt;span class="sd"&gt;    provider tree.&lt;/span&gt;

&lt;span class="sd"&gt;    :returns: A dict, keyed by consumer UUID, of allocation records.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A consumer isn’t always an instance (it may be a “migration” - or other things
not created by Nova, in the future), so we can’t just use the instance list as
the consumer list.&lt;/p&gt;
&lt;p&gt;We can’t get &lt;em&gt;all&lt;/em&gt; allocations for associated sharing providers because some of
those will belong to consumers on other hosts.&lt;/p&gt;
&lt;p&gt;So we have to discover all the consumers associated with the providers in the
local tree:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="s2"&gt;"local"&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resource_providers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;allocations&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can’t use &lt;em&gt;just&lt;/em&gt; those allocations because we would miss allocations for
sharing providers. So we have to get all the allocations for just the consumers
discovered above:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We will still miss data if &lt;strong&gt;all&lt;/strong&gt; of a consumer’s allocations live
on sharing providers. I don’t have a good way to close that hole.
But that scenario won’t happen in the near future, so it’ll be noted
as a limitation via a code comment.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Return a dict, keyed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{consumer.uuid}&lt;/span&gt;&lt;/code&gt;, of the resulting allocation
records. This is the form of the new &lt;a class="reference internal" href="#allocations-parameter"&gt;Allocations Parameter&lt;/a&gt; expected by
&lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree()&lt;/a&gt; and &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree()&lt;/a&gt;), and return it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reshapeneeded-exception"&gt;
&lt;h3&gt;ReshapeNeeded exception&lt;/h3&gt;
&lt;p&gt;A new exception, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeNeeded&lt;/span&gt;&lt;/code&gt;, will be introduced. It is used as a signal
from &lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree()&lt;/a&gt; to indicate that a reshape must be performed.
This is for performance reasons so that we don’t
&lt;a class="reference internal" href="#get-allocations-for-provider-tree"&gt;get_allocations_for_provider_tree()&lt;/a&gt; unless it’s necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="changes-to-update-provider-tree"&gt;
&lt;span id="update-provider-tree"/&gt;&lt;h3&gt;Changes to update_provider_tree()&lt;/h3&gt;
&lt;section id="allocations-parameter"&gt;
&lt;h4&gt;Allocations Parameter&lt;/h4&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; keyword argument will be added to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;upgrade_provider_tree()&lt;/span&gt;&lt;/code&gt; method must not perform a reshape.
If it decides a reshape is necessary, it must raise the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeNeeded&lt;/span&gt;&lt;/code&gt;
exception.&lt;/p&gt;
&lt;p&gt;When not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; argument is a dict, keyed by consumer
UUID, of allocation records of the form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{ $CONSUMER_UUID: {
      # NOTE: The shape of each "allocations" dict below is identical to the
      # return from GET /allocations/{consumer_uuid}...
      "allocations": {
          $RP_UUID: {
              "generation": $RP_GEN,
              "resources": {
                  $RESOURCE_CLASS: $AMOUNT,
                  ...
              },
          },
          ...
      },
      "project_id": $PROJ_ID,
      "user_id": $USER_ID,
      # ...except for this, which is coming in bp/add-consumer-generation
      "consumer_generation": $CONSUMER_GEN,
  },
  ...
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; is moving allocations, it must edit the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; dict in place.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;I don’t love the idea of the method editing the dict in place rather
than returning a copy, but it’s consistent with how we’re handling
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;provider_tree&lt;/span&gt;&lt;/code&gt; arg.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="virt-drivers"&gt;
&lt;h4&gt;Virt Drivers&lt;/h4&gt;
&lt;p&gt;Virt drivers currently overriding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; will need to
change the signature to accomodate the new parameter. That work will be done
within the scope of this blueprint.&lt;/p&gt;
&lt;p&gt;As virt drivers begin to model resources in nested providers, their
implementations will need to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;determine whether a reshape is necessary and raise &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeNeeded&lt;/span&gt;&lt;/code&gt; as
appropriate;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;perform the reshape by processing provider inventories and the specified
allocations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That work is outside the scope of this blueprint.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="changes-to-update-from-provider-tree"&gt;
&lt;span id="update-from-provider-tree"/&gt;&lt;h3&gt;Changes to update_from_provider_tree()&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SchedulerReportClient.update_from_provider_tree()&lt;/span&gt;&lt;/code&gt; method is changed to
accept a new parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update_from_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Flush changes from a specified ProviderTree back to placement.&lt;/span&gt;

&lt;span class="sd"&gt;    ...&lt;/span&gt;

&lt;span class="sd"&gt;    ...&lt;/span&gt;
&lt;span class="sd"&gt;    :param allocations: A dict, keyed by consumer UUID, of allocation records&lt;/span&gt;
&lt;span class="sd"&gt;            of the form returned by GET /allocations/{consumer_uuid}. The&lt;/span&gt;
&lt;span class="sd"&gt;            dict must represent the comprehensive final picture of the&lt;/span&gt;
&lt;span class="sd"&gt;            allocations for each consumer therein. A value of None indicates&lt;/span&gt;
&lt;span class="sd"&gt;            that no reshape is being performed.&lt;/span&gt;
&lt;span class="sd"&gt;    ...&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, the behavior of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_from_provider_tree()&lt;/span&gt;&lt;/code&gt; is as it was previously (in Queens).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="changes-to-resource-tracker-update"&gt;
&lt;span id="resource-tracker-update"/&gt;&lt;h3&gt;Changes to Resource Tracker _update()&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_update()&lt;/span&gt;&lt;/code&gt; method will get a new parameter, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;startup&lt;/span&gt;&lt;/code&gt;, which is
percolated down from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Where &lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree()&lt;/a&gt; and &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree()&lt;/a&gt; are
currently invoked, the code flow will be changed to approximately:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prov_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReshapeNeeded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Treat this like a regular exception during periodic&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
    &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Performing resource provider inventory and "&lt;/span&gt;
             &lt;span class="s2"&gt;"allocation data migration during compute service "&lt;/span&gt;
             &lt;span class="s2"&gt;"startup or FFU."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;allocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reportclient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_allocations_for_provider_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prov_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;allocs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;reportclient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_from_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prov_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allocs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="changes-to-update-available-resource-for-node"&gt;
&lt;h3&gt;Changes to _update_available_resource_for_node()&lt;/h3&gt;
&lt;p&gt;This is currently where all exceptions for the &lt;a class="reference internal" href="#resource-tracker-update"&gt;Resource Tracker _update()&lt;/a&gt;
periodic task are caught, logged, and otherwise ignored.&lt;/p&gt;
&lt;p&gt;We will add a new parameter, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;startup&lt;/span&gt;&lt;/code&gt;, percolated down from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource()&lt;/span&gt;&lt;/code&gt;, and a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;except&lt;/span&gt;&lt;/code&gt; clause of the form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceProviderUpdateFailed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Kill the compute service.&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
    &lt;span class="c1"&gt;# Else log a useful exception reporting what happened and maybe even how&lt;/span&gt;
    &lt;span class="c1"&gt;# to fix it; and then carry on.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The purpose of this is to make exceptions in &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree()&lt;/a&gt;
fatal on startup only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="placement-post-reshaper"&gt;
&lt;h3&gt;Placement POST /reshaper&lt;/h3&gt;
&lt;p&gt;In a new placement microversion, a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/reshaper&lt;/span&gt;&lt;/code&gt; operation will be
introduced. The payload is of the form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
  "inventories": [
    $RP_UUID: {
      # This is the exact payload format for
      # PUT /resource_provider/$RP_UUID/inventories.
      # It should represent the final state of the entire set of resources
      # for this provider. In particular, omitting a $RC dict will cause the
      # inventory for that resource class to be deleted if previously present.
      "inventories": { $RC: { &amp;lt;total, reserved, etc.&amp;gt; } }
      "resource_provider_generation": &amp;lt;gen of this RP&amp;gt;,
    },
    $RP_UUID: { ... },
  ],
  "allocations": [
    # This is the exact payload format for POST /allocations
    $CONSUMER_UUID: {
      "project_id": $PROJ_ID,
      "user_id": $USER_ID,
      # This field is part of the consumer generation series under review,
      # not yet in the published POST /allocations payload.
      "consumer_generation": $CONSUMER_GEN,
      "allocations": {
        $RP_UUID: {
          "resources": { $RC: $AMOUNT, ... }
        },
        $RP_UUID: { ... }
      }
    },
    $CONSUMER_UUID: { ... }
  ]
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In a single atomic transaction, placement replaces the inventories for each
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$RP_UUID&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inventories&lt;/span&gt;&lt;/code&gt; dict; and replaces the allocations for each
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$CONSUMER_UUID&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;
&lt;p&gt;Return values:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;204&lt;/span&gt; &lt;span class="pre"&gt;No&lt;/span&gt; &lt;span class="pre"&gt;Content&lt;/span&gt;&lt;/code&gt; on success.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; on any provider or consumer generation conflict; or if a
concurrent transaction is detected. Appropriate error codes should be used
for at least the former so the caller can tell whether a fresh &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; is
necessary before recalculating the necessary reshapes and retrying the
operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;Bad&lt;/span&gt; &lt;span class="pre"&gt;Request&lt;/span&gt;&lt;/code&gt; on any other failure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="direct-interface-to-placement"&gt;
&lt;h3&gt;Direct Interface to Placement&lt;/h3&gt;
&lt;p&gt;To make the &lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt; possible, we need to make placement
accessible by importing Python code rather than as a standalone service. The
quickest path forward is to use &lt;a class="reference external" href="https://pypi.org/project/wsgi_intercept/"&gt;wsgi-intercept&lt;/a&gt; to allow HTTP interactions,
using the &lt;a class="reference external" href="http://docs.python-requests.org/"&gt;requests&lt;/a&gt; library, to work with only database traffic going over
the network. This allows client code to make changes to the placement data
store using the same API, but without running a placement service.&lt;/p&gt;
&lt;p&gt;An implementation of this, as a context manager called &lt;a class="reference external" href="https://review.openstack.org/#/c/572576/"&gt;PlacementDirect&lt;/a&gt;, is
merged. The context manager accepts an &lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/"&gt;oslo config&lt;/a&gt;, populated by the
caller. This allows the calling code to control how it wishes to discover
configuration settings, most importantly the database being used by placement.&lt;/p&gt;
&lt;p&gt;This implementation provides a quick solution to the immediate needs of offline
use of &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; while allowing options for prettier
solutions in the future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="offline-upgrade-script"&gt;
&lt;h3&gt;Offline Upgrade Script&lt;/h3&gt;
&lt;p&gt;To facilitate Fast Forward Upgrades, we will provide a script that can perform
this reshaping while all services (except databases) are offline. It will look
like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;placement&lt;/span&gt; &lt;span class="n"&gt;migrate_compute_inventory&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;…and operate as follows, for each nodename (one, except for ironic) on the
host:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Spin up a SchedulerReportClient with a &lt;a class="reference internal" href="#direct-interface-to-placement"&gt;Direct Interface to Placement&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieve a ProviderTree via
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SchedulerReportClient.get_provider_tree_and_ensure_root()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instantiate the appropriate virt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform the algorithm noted in &lt;a class="reference internal" href="#resource-tracker-update"&gt;Resource Tracker _update()&lt;/a&gt;, as if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;startup&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We may refer to &lt;a class="reference external" href="https://review.openstack.org/#/c/501025/"&gt;https://review.openstack.org/#/c/501025/&lt;/a&gt; for an example of an
upgrade script that requires a virt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="reshaper-api"&gt;
&lt;h4&gt;Reshaper API&lt;/h4&gt;
&lt;p&gt;Alternatives to &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; were discussed in the &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-May/130783.html"&gt;mailing list
thread&lt;/a&gt;, the &lt;a class="reference external" href="https://etherpad.openstack.org/p/placement-migrate-operations"&gt;etherpad&lt;/a&gt;, IRC, hangout, etc. They included:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Don’t have an atomic placement operation - do the necessary operations one at
a time from the resource tracker. Rejected due to race conditions: the
scheduler can schedule against the moving inventories, based on incorrect
capacity information due to the moving allocations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Lock” the moving inventories - either by providing a locking API or by
setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;total&lt;/span&gt;&lt;/code&gt; - while the resource tracker does the
reshape. Rejected because it’s a hack; and because recovery from partial
failures would be difficult.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Merge” forms of the new placement operation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;&lt;/code&gt;) with &lt;a class="reference external" href="https://tools.ietf.org/html/rfc6902"&gt;RFC 6902&lt;/a&gt;-style &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"operation",&lt;/span&gt; &lt;span class="pre"&gt;"path"[,&lt;/span&gt;
&lt;span class="pre"&gt;"from",&lt;/span&gt; &lt;span class="pre"&gt;"value"]&lt;/span&gt;&lt;/code&gt; instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;&lt;/code&gt;) with &lt;a class="reference external" href="https://tools.ietf.org/html/rfc7396"&gt;RFC 7396&lt;/a&gt; semantics. The JSON payload would
look like a sparse version of that described in &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST
/reshaper&lt;/a&gt;, but with only changes included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other payload formats for the placement operation (see the &lt;a class="reference external" href="https://etherpad.openstack.org/p/placement-migrate-operations"&gt;etherpad&lt;/a&gt;). We
chose the one we did because it reuses existing payload syntax (and may
therefore be able to reuse code) and it provides a full specification of the
expected end state, which is RESTy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="direct-placement"&gt;
&lt;h4&gt;Direct Placement&lt;/h4&gt;
&lt;p&gt;Alternatives to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi-intercept&lt;/span&gt;&lt;/code&gt; model for the &lt;a class="reference internal" href="#direct-interface-to-placement"&gt;Direct Interface to
Placement&lt;/a&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Directly access the object methods (with some refactoring/cleanup). Rejected
because we lose things like schema validation and microversion logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create cleaner, pythonic wrappers around those object methods. Rejected (in
the short term) for the sake of expediency. We might take this approach
longer-term as/when the demand for direct placement expands beyond FFU
scripting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi-intercept&lt;/span&gt;&lt;/code&gt; but create the pythonic wrappers outside of the REST
layer. This is also a long-term option.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="reshaping-via-update-provider-tree"&gt;
&lt;h4&gt;Reshaping Via update_provider_tree()&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We considered passing allocations to &lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree()&lt;/a&gt; every time,
but gathering the allocations will be expensive, so we needed a way to do it
only when necessary. Enter &lt;a class="reference internal" href="#reshapeneeded-exception"&gt;ReshapeNeeded exception&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We considered running the check-and-reshape-if-needed algorithm on every
periodic interval, but decided we should never need to do a reshape except on
startup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade Impact&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The new &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; operation has the potential to be slow, and
to lock several tables. Its use should be restricted to reshaping provider
trees. Initially we may use the reshaper from &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree()&lt;/a&gt;
even if no reshape is being performed; but if this is found to be problematic
for performance, we can restrict it to only reshape scenarios, which will be
very rare.&lt;/p&gt;
&lt;p&gt;Gathering allocations, particularly in large deployments, has the potential to
be heavy and slow, so we only do this at compute startup, and then only if
&lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree()&lt;/a&gt; indicates that a reshape is necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade Impact&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#virt-drivers"&gt;Virt Drivers&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Live upgrades are covered. The &lt;a class="reference internal" href="#resource-tracker-update"&gt;Resource Tracker _update()&lt;/a&gt; flow will run on
compute start and perform the reshape as necessary. Since we do not support
skipping releases on live upgrades, any virt driver-specific changes can be
removed from one release to the next.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt; is provided for Fast-Forward Upgrade. Since code
is run with each release’s codebase for each step in the FFU, any virt
driver-specific changes can be removed from one release to the next. Note,
however, that the script must &lt;strong&gt;always be run&lt;/strong&gt; since only the virt driver,
running on a specific compute, can determine whether a reshape is required for
that compute. (If no reshape is necessary, the script is a no-op.)&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt;: jaypipes (SQL-fu), cdent (API plumbing)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#direct-interface-to-placement"&gt;Direct Interface to Placement&lt;/a&gt;: cdent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report client, resource tracker, virt driver parity: efried&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt;: dansmith&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reviews and general heckling: mriedem, bauzas, gibi, edleafe, alex_xu&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/add-consumer-generation.html"&gt;Consumer Generations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/nested-resource-providers-allocation-candidates.html"&gt;Nested Resource Providers - Allocation Candidates&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional test enhancements for everyone, including gabbi tests for &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement
POST /reshaper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Live testing in Xen (naichuans) and libvirt (bauzas) via their VGPU work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; (placement API reference)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt; (&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html#nova-database"&gt;nova-manage db&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/add-consumer-generation.html"&gt;Consumer Generations&lt;/a&gt; spec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/nested-resource-providers-allocation-candidates.html"&gt;Nested Resource Providers - Allocation Candidates&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Placement reshaper API discussion &lt;a class="reference external" href="https://etherpad.openstack.org/p/placement-migrate-operations"&gt;etherpad&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade concerns… &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-May/130783.html"&gt;mailing list thread&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc6902"&gt;RFC 6902&lt;/a&gt; (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;json-patch+json&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc7396"&gt;RFC 7396&lt;/a&gt; (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;merge-patch+json&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html#nova-database"&gt;nova-manage db&lt;/a&gt; migration helper docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/wsgi_intercept/"&gt;wsgi-intercept&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python &lt;a class="reference external" href="http://docs.python-requests.org/"&gt;requests&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/572576/"&gt;PlacementDirect&lt;/a&gt; implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/"&gt;oslo config&lt;/a&gt; library&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 05 Jul 2023 00:00:00 </pubDate></item><item><title>Handling Reshaped Provider Trees</title><link>https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/reshape-provider-tree.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/reshape-provider-tree"&gt;https://blueprints.launchpad.net/nova/+spec/reshape-provider-tree&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Virt drivers need to be able to change the structure of the provider trees they
expose. When moving existing resources, existing allocations need to be moved
along with the inventories. And this must be done in such a way as to avoid
races where a second entity can create or remove allocations against the moving
inventories.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The libvirt driver currently inventories VGPU resources on the compute node
provider. In order to exploit provider trees, libvirt needs to create one
child provider per physical GPU and move the VGPU inventory from the compute
node provider to these GPU child providers. In a live deployment where VGPU
resources are already allocated to instances, the allocations need to be
moved along with the inventories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drivers wishing to model NUMA must similarly create child providers and move
inventory and allocations of several classes (processor, memory, VFs on
NUMA-affined NICs, etc.) to those providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A driver is using a custom resource class. That resource class is added to
the standard set (under a new, non-&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_&lt;/span&gt;&lt;/code&gt; name). In order to use the
standard name, the driver must move inventory and allocations from the old
name to the new.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are just example cases that may exist now or in the future.  We’re
describing a generic pivot system here.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The overall flow is as follows. The parts in red only happen when a reshape is
needed. This represents the happy path on compute startup only.&lt;/p&gt;
&lt;img alt="../../../_images/reshape-provider-tree1.svg" src="../../../_images/reshape-provider-tree1.svg"/&gt;
&lt;p&gt;Note that, for Fast-Forward Upgrades, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Resource&lt;/span&gt; &lt;span class="pre"&gt;Tracker&lt;/span&gt;&lt;/code&gt; lane is actually
the &lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt;.&lt;/p&gt;
&lt;section id="schedulerreportclient-get-allocations-for-provider-tree"&gt;
&lt;span id="get-allocations-for-provider-tree"/&gt;&lt;h3&gt;SchedulerReportClient.get_allocations_for_provider_tree()&lt;/h3&gt;
&lt;p&gt;A new SchedulerReportClient method shall be implemented:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get_allocations_for_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Retrieve allocation records associated with all providers in the&lt;/span&gt;
&lt;span class="sd"&gt;    provider tree.&lt;/span&gt;

&lt;span class="sd"&gt;    :param context: The security context&lt;/span&gt;
&lt;span class="sd"&gt;    :param nodename: The name of a node for whose tree we are getting&lt;/span&gt;
&lt;span class="sd"&gt;            allocations.&lt;/span&gt;
&lt;span class="sd"&gt;    :returns: A dict, keyed by consumer UUID, of allocation records:&lt;/span&gt;
&lt;span class="sd"&gt;            { $CONSUMER_UUID: {&lt;/span&gt;
&lt;span class="sd"&gt;                  # The shape of each "allocations" dict below is identical&lt;/span&gt;
&lt;span class="sd"&gt;                  # to the return from GET /allocations/{consumer_uuid}&lt;/span&gt;
&lt;span class="sd"&gt;                  "allocations": {&lt;/span&gt;
&lt;span class="sd"&gt;                      $RP_UUID: {&lt;/span&gt;
&lt;span class="sd"&gt;                          "generation": $RP_GEN,&lt;/span&gt;
&lt;span class="sd"&gt;                          "resources": {&lt;/span&gt;
&lt;span class="sd"&gt;                              $RESOURCE_CLASS: $AMOUNT,&lt;/span&gt;
&lt;span class="sd"&gt;                              ...&lt;/span&gt;
&lt;span class="sd"&gt;                          },&lt;/span&gt;
&lt;span class="sd"&gt;                      },&lt;/span&gt;
&lt;span class="sd"&gt;                      ...&lt;/span&gt;
&lt;span class="sd"&gt;                  },&lt;/span&gt;
&lt;span class="sd"&gt;                  "project_id": $PROJ_ID,&lt;/span&gt;
&lt;span class="sd"&gt;                  "user_id": $USER_ID,&lt;/span&gt;
&lt;span class="sd"&gt;                  "consumer_generation": $CONSUMER_GEN,&lt;/span&gt;
&lt;span class="sd"&gt;              },&lt;/span&gt;
&lt;span class="sd"&gt;              ...&lt;/span&gt;
&lt;span class="sd"&gt;            }&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A consumer isn’t always an instance (it may be a “migration” - or other things
not created by Nova, in the future), so we can’t just use the instance list as
the consumer list.&lt;/p&gt;
&lt;p&gt;We can’t get &lt;em&gt;all&lt;/em&gt; allocations for associated sharing providers because some of
those will belong to consumers on other hosts.&lt;/p&gt;
&lt;p&gt;So we have to discover all the consumers associated with the providers in the
“local” tree (identified by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nodename&lt;/span&gt;&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="s2"&gt;"local"&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resource_providers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;allocations&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can’t use &lt;em&gt;just&lt;/em&gt; those allocations because we would miss allocations for
sharing providers. So we have to get all the allocations for just the consumers
discovered above:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We will still miss data if &lt;strong&gt;all&lt;/strong&gt; of a consumer’s allocations live
on sharing providers. I don’t have a good way to close that hole.
But that scenario won’t happen in the near future, so it’ll be noted
as a limitation via a code comment.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Return a dict, keyed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{consumer.uuid}&lt;/span&gt;&lt;/code&gt;, of the resulting allocation
records. This is the form of the new &lt;a class="reference internal" href="#allocations-parameter"&gt;Allocations Parameter&lt;/a&gt; expected by
&lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree&lt;/a&gt; and &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree&lt;/a&gt;), and return it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reshapeneeded-exception"&gt;
&lt;h3&gt;ReshapeNeeded exception&lt;/h3&gt;
&lt;p&gt;A new exception, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeNeeded&lt;/span&gt;&lt;/code&gt;, will be introduced. It is used as a signal
from &lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree&lt;/a&gt; to indicate that a reshape must be performed.
This is for performance reasons so that we don’t
&lt;a class="reference internal" href="#get-allocations-for-provider-tree"&gt;get_allocations_for_provider_tree&lt;/a&gt; unless it’s necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reshapefailed-exception"&gt;
&lt;span id="update-provider-tree"/&gt;&lt;h3&gt;ReshapeFailed exception&lt;/h3&gt;
&lt;p&gt;A new exception, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeFailed&lt;/span&gt;&lt;/code&gt;, will be introduced. It is raised from
&lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree&lt;/a&gt; only when reshaping is needed, attempted, and
unsuccessful (i.e. when the &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; call fails). This is so
we can trap it explicitly in &lt;a class="reference internal" href="#update-available-resource-for-node"&gt;_update_available_resource_for_node&lt;/a&gt; and kill
the compute service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="changes-to-update-provider-tree"&gt;
&lt;h3&gt;Changes to update_provider_tree()&lt;/h3&gt;
&lt;section id="allocations-parameter"&gt;
&lt;h4&gt;Allocations Parameter&lt;/h4&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; keyword argument will be added to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;upgrade_provider_tree()&lt;/span&gt;&lt;/code&gt; method must not perform a reshape.
If it decides a reshape is necessary, it must raise the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeNeeded&lt;/span&gt;&lt;/code&gt;
exception.&lt;/p&gt;
&lt;p&gt;When not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; argument is a dict, keyed by consumer
UUID, of allocation records of the form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{ $CONSUMER_UUID: {
      # NOTE: The shape of each "allocations" dict below is identical to the
      # return from GET /allocations/{consumer_uuid}...
      "allocations": {
          $RP_UUID: {
              "generation": $RP_GEN,
              "resources": {
                  $RESOURCE_CLASS: $AMOUNT,
                  ...
              },
          },
          ...
      },
      "project_id": $PROJ_ID,
      "user_id": $USER_ID,
      # ...except for this, which is coming in bp/add-consumer-generation
      "consumer_generation": $CONSUMER_GEN,
  },
  ...
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; is moving allocations, it must edit the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; dict in place.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;I don’t love the idea of the method editing the dict in place rather
than returning a copy, but it’s consistent with how we’re handling
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;provider_tree&lt;/span&gt;&lt;/code&gt; arg.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="virt-drivers"&gt;
&lt;h4&gt;Virt Drivers&lt;/h4&gt;
&lt;p&gt;Virt drivers currently overriding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; will need to
change the signature to accomodate the new parameter. That work will be done
within the scope of this blueprint.&lt;/p&gt;
&lt;p&gt;As virt drivers begin to model resources in nested providers, their
implementations will need to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;determine whether a reshape is necessary and raise &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ReshapeNeeded&lt;/span&gt;&lt;/code&gt; as
appropriate;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;perform the reshape by processing provider inventories and the specified
allocations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That work is outside the scope of this blueprint.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="changes-to-update-from-provider-tree"&gt;
&lt;span id="update-from-provider-tree"/&gt;&lt;h3&gt;Changes to update_from_provider_tree()&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SchedulerReportClient.update_from_provider_tree()&lt;/span&gt;&lt;/code&gt; method is changed to
accept a new parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update_from_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Flush changes from a specified ProviderTree back to placement.&lt;/span&gt;

&lt;span class="sd"&gt;    ...&lt;/span&gt;

&lt;span class="sd"&gt;    ...&lt;/span&gt;
&lt;span class="sd"&gt;    :param allocations: A dict, keyed by consumer UUID, of allocation records&lt;/span&gt;
&lt;span class="sd"&gt;            of the form returned by GET /allocations/{consumer_uuid}. The&lt;/span&gt;
&lt;span class="sd"&gt;            dict must represent the comprehensive final picture of the&lt;/span&gt;
&lt;span class="sd"&gt;            allocations for each consumer therein. A value of None indicates&lt;/span&gt;
&lt;span class="sd"&gt;            that no reshape is being performed.&lt;/span&gt;
&lt;span class="sd"&gt;    ...&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, the behavior of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_from_provider_tree()&lt;/span&gt;&lt;/code&gt; is as it was previously (in Queens).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="changes-to-resource-tracker-update"&gt;
&lt;span id="resource-tracker-update"/&gt;&lt;h3&gt;Changes to Resource Tracker _update()&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_update()&lt;/span&gt;&lt;/code&gt; method will get a new parameter, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;startup&lt;/span&gt;&lt;/code&gt;, which is
percolated down from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Where &lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree&lt;/a&gt; and &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree&lt;/a&gt; are
currently invoked, the code flow will be changed to approximately:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prov_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReshapeNeeded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# This isn't supposed to happen during periodic, so raise&lt;/span&gt;
        &lt;span class="c1"&gt;# it up; the compute manager will treat it specially,&lt;/span&gt;
        &lt;span class="c1"&gt;# killing the compute service.&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
    &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Performing resource provider inventory and "&lt;/span&gt;
             &lt;span class="s2"&gt;"allocation data migration during compute service "&lt;/span&gt;
             &lt;span class="s2"&gt;"startup or FFU."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;allocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reportclient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_allocations_for_provider_tree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prov_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;allocations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;allocs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;reportclient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_from_provider_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prov_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allocs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="changes-to-update-available-resource-for-node"&gt;
&lt;span id="update-available-resource-for-node"/&gt;&lt;h3&gt;Changes to _update_available_resource_for_node()&lt;/h3&gt;
&lt;p&gt;This is currently where all exceptions for the &lt;a class="reference internal" href="#resource-tracker-update"&gt;Resource Tracker _update&lt;/a&gt;
periodic task are caught, logged, and otherwise ignored. We will add new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;except&lt;/span&gt;&lt;/code&gt; conditions for reshape-related exceptions that will actually blow up
the compute service (i.e.  not log-and-otherwise-ignore). These exceptions
should only legitimately reach this method on startup.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="placement-post-reshaper"&gt;
&lt;h3&gt;Placement POST /reshaper&lt;/h3&gt;
&lt;p&gt;In a new placement microversion, a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/reshaper&lt;/span&gt;&lt;/code&gt; operation will be
introduced. The payload is of the form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
  "inventories": {
    $RP_UUID: {
      # This is the exact payload format for
      # PUT /resource_provider/$RP_UUID/inventories.
      # It should represent the final state of the entire set of resources
      # for this provider. In particular, omitting a $RC dict will cause the
      # inventory for that resource class to be deleted if previously present.
      "inventories": { $RC: { &amp;lt;total, reserved, etc.&amp;gt; } }
      "resource_provider_generation": &amp;lt;gen of this RP&amp;gt;,
    },
    $RP_UUID: { ... },
  },
  "allocations": {
    # This is the exact payload format for POST /allocations
    $CONSUMER_UUID: {
      "project_id": $PROJ_ID,
      "user_id": $USER_ID,
      # This field is part of the consumer generation series under review,
      # not yet in the published POST /allocations payload.
      "consumer_generation": $CONSUMER_GEN,
      "allocations": {
        $RP_UUID: {
          "resources": { $RC: $AMOUNT, ... }
        },
        $RP_UUID: { ... }
      }
    },
    $CONSUMER_UUID: { ... }
  }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In a single atomic transaction, placement replaces the inventories for each
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$RP_UUID&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inventories&lt;/span&gt;&lt;/code&gt; dict; and replaces the allocations for each
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$CONSUMER_UUID&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;
&lt;p&gt;Return values:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;204&lt;/span&gt; &lt;span class="pre"&gt;No&lt;/span&gt; &lt;span class="pre"&gt;Content&lt;/span&gt;&lt;/code&gt; on success.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; on any provider or consumer generation conflict; or if a
concurrent transaction is detected. Appropriate error codes should be used
for at least the former so the caller can tell whether a fresh &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; is
necessary before recalculating the necessary reshapes and retrying the
operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;Bad&lt;/span&gt; &lt;span class="pre"&gt;Request&lt;/span&gt;&lt;/code&gt; on any other failure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="direct-interface-to-placement"&gt;
&lt;h3&gt;Direct Interface to Placement&lt;/h3&gt;
&lt;p&gt;To make the &lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt; possible, we need to make placement
accessible by importing Python code rather than as a standalone service. The
quickest path forward is to use &lt;a class="reference external" href="https://pypi.org/project/wsgi_intercept/"&gt;wsgi-intercept&lt;/a&gt; to allow HTTP interactions,
using the &lt;a class="reference external" href="http://docs.python-requests.org/"&gt;requests&lt;/a&gt; library, to work with only database traffic going over
the network. This allows client code to make changes to the placement data
store using the same API, but without running a placement service.&lt;/p&gt;
&lt;p&gt;An implementation of this, as a context manager called &lt;a class="reference external" href="https://review.openstack.org/#/c/572576/"&gt;PlacementDirect&lt;/a&gt;, is
merged. The context manager accepts an &lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/"&gt;oslo config&lt;/a&gt;, populated by the
caller. This allows the calling code to control how it wishes to discover
configuration settings, most importantly the database being used by placement.&lt;/p&gt;
&lt;p&gt;This implementation provides a quick solution to the immediate needs of offline
use of &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; while allowing options for prettier
solutions in the future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="offline-upgrade-script"&gt;
&lt;h3&gt;Offline Upgrade Script&lt;/h3&gt;
&lt;p&gt;To facilitate Fast Forward Upgrades, we will provide a script that can perform
this reshaping while all services (except databases) are offline. It will look
like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;placement&lt;/span&gt; &lt;span class="n"&gt;migrate_compute_inventory&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;…and operate as follows, for each nodename (one, except for ironic) on the
host:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Spin up a SchedulerReportClient with a &lt;a class="reference internal" href="#direct-interface-to-placement"&gt;Direct Interface to Placement&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieve a ProviderTree via
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SchedulerReportClient.get_provider_tree_and_ensure_root()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instantiate the appropriate virt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform the algorithm noted in &lt;a class="reference internal" href="#resource-tracker-update"&gt;Resource Tracker _update&lt;/a&gt;, as if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;startup&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We may refer to &lt;a class="reference external" href="https://review.openstack.org/#/c/501025/"&gt;https://review.openstack.org/#/c/501025/&lt;/a&gt; for an example of an
upgrade script that requires a virt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="reshaper-api"&gt;
&lt;h4&gt;Reshaper API&lt;/h4&gt;
&lt;p&gt;Alternatives to &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; were discussed in the &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-May/130783.html"&gt;mailing list
thread&lt;/a&gt;, the &lt;a class="reference external" href="https://etherpad.openstack.org/p/placement-migrate-operations"&gt;etherpad&lt;/a&gt;, IRC, hangout, etc. They included:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Don’t have an atomic placement operation - do the necessary operations one at
a time from the resource tracker. Rejected due to race conditions: the
scheduler can schedule against the moving inventories, based on incorrect
capacity information due to the moving allocations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Lock” the moving inventories - either by providing a locking API or by
setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;total&lt;/span&gt;&lt;/code&gt; - while the resource tracker does the
reshape. Rejected because it’s a hack; and because recovery from partial
failures would be difficult.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Merge” forms of the new placement operation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;&lt;/code&gt;) with &lt;a class="reference external" href="https://tools.ietf.org/html/rfc6902"&gt;RFC 6902&lt;/a&gt;-style &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"operation",&lt;/span&gt; &lt;span class="pre"&gt;"path"[,&lt;/span&gt;
&lt;span class="pre"&gt;"from",&lt;/span&gt; &lt;span class="pre"&gt;"value"]&lt;/span&gt;&lt;/code&gt; instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;&lt;/code&gt;) with &lt;a class="reference external" href="https://tools.ietf.org/html/rfc7396"&gt;RFC 7396&lt;/a&gt; semantics. The JSON payload would
look like a sparse version of that described in &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST
/reshaper&lt;/a&gt;, but with only changes included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other payload formats for the placement operation (see the &lt;a class="reference external" href="https://etherpad.openstack.org/p/placement-migrate-operations"&gt;etherpad&lt;/a&gt;). We
chose the one we did because it reuses existing payload syntax (and may
therefore be able to reuse code) and it provides a full specification of the
expected end state, which is RESTy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="direct-placement"&gt;
&lt;h4&gt;Direct Placement&lt;/h4&gt;
&lt;p&gt;Alternatives to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi-intercept&lt;/span&gt;&lt;/code&gt; model for the &lt;a class="reference internal" href="#direct-interface-to-placement"&gt;Direct Interface to
Placement&lt;/a&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Directly access the object methods (with some refactoring/cleanup). Rejected
because we lose things like schema validation and microversion logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create cleaner, pythonic wrappers around those object methods. Rejected (in
the short term) for the sake of expediency. We might take this approach
longer-term as/when the demand for direct placement expands beyond FFU
scripting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi-intercept&lt;/span&gt;&lt;/code&gt; but create the pythonic wrappers outside of the REST
layer. This is also a long-term option.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="reshaping-via-update-provider-tree"&gt;
&lt;h4&gt;Reshaping Via update_provider_tree()&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We considered passing allocations to &lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree&lt;/a&gt; every time,
but gathering the allocations will be expensive, so we needed a way to do it
only when necessary. Enter &lt;a class="reference internal" href="#reshapeneeded-exception"&gt;ReshapeNeeded exception&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We considered running the check-and-reshape-if-needed algorithm on every
periodic interval, but decided we should never need to do a reshape except on
startup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade Impact&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The new &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; operation has the potential to be slow, and
to lock several tables. Its use should be restricted to reshaping provider
trees. Initially we may use the reshaper from &lt;a class="reference internal" href="#update-from-provider-tree"&gt;update_from_provider_tree&lt;/a&gt;
even if no reshape is being performed; but if this is found to be problematic
for performance, we can restrict it to only reshape scenarios, which will be
very rare.&lt;/p&gt;
&lt;p&gt;Gathering allocations, particularly in large deployments, has the potential to
be heavy and slow, so we only do this at compute startup, and then only if
&lt;a class="reference internal" href="#update-provider-tree"&gt;update_provider_tree&lt;/a&gt; indicates that a reshape is necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade Impact&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#virt-drivers"&gt;Virt Drivers&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Live upgrades are covered. The &lt;a class="reference internal" href="#resource-tracker-update"&gt;Resource Tracker _update&lt;/a&gt; flow will run on
compute start and perform the reshape as necessary. Since we do not support
skipping releases on live upgrades, any virt driver-specific changes can be
removed from one release to the next.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt; is provided for Fast-Forward Upgrade. Since code
is run with each release’s codebase for each step in the FFU, any virt
driver-specific changes can be removed from one release to the next. Note,
however, that the script must &lt;strong&gt;always be run&lt;/strong&gt; since only the virt driver,
running on a specific compute, can determine whether a reshape is required for
that compute. (If no reshape is necessary, the script is a no-op.)&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt;: jaypipes (SQL-fu), cdent (API plumbing)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#direct-interface-to-placement"&gt;Direct Interface to Placement&lt;/a&gt;: cdent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report client, resource tracker, virt driver parity: efried&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt;: dansmith&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reviews and general heckling: mriedem, bauzas, gibi, edleafe, alex_xu&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/add-consumer-generation.html"&gt;Consumer Generations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/nested-resource-providers-allocation-candidates.html"&gt;Nested Resource Providers - Allocation Candidates&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional test enhancements for everyone, including gabbi tests for &lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement
POST /reshaper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Live testing in Xen (naichuans) and libvirt (bauzas) via their VGPU work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#placement-post-reshaper"&gt;Placement POST /reshaper&lt;/a&gt; (placement API reference)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#offline-upgrade-script"&gt;Offline Upgrade Script&lt;/a&gt; (&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html#nova-database"&gt;nova-manage db&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/add-consumer-generation.html"&gt;Consumer Generations&lt;/a&gt; spec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/rocky/approved/nested-resource-providers-allocation-candidates.html"&gt;Nested Resource Providers - Allocation Candidates&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Placement reshaper API discussion &lt;a class="reference external" href="https://etherpad.openstack.org/p/placement-migrate-operations"&gt;etherpad&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade concerns… &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-May/130783.html"&gt;mailing list thread&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc6902"&gt;RFC 6902&lt;/a&gt; (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;json-patch+json&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc7396"&gt;RFC 7396&lt;/a&gt; (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;merge-patch+json&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html#nova-database"&gt;nova-manage db&lt;/a&gt; migration helper docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/wsgi_intercept/"&gt;wsgi-intercept&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python &lt;a class="reference external" href="http://docs.python-requests.org/"&gt;requests&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/572576/"&gt;PlacementDirect&lt;/a&gt; implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/"&gt;oslo config&lt;/a&gt; library&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 05 Jul 2023 00:00:00 </pubDate></item><item><title>Nova - Cyborg Interaction</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/approved/nova-cyborg-interaction.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-cyborg-interaction"&gt;https://blueprints.launchpad.net/nova/+spec/nova-cyborg-interaction&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification describes the Nova - Cyborg interaction needed to create
and manage instances with accelerators, and the changes needed in Nova to
accomplish that.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="scope"&gt;
&lt;h3&gt;Scope&lt;/h3&gt;
&lt;p&gt;Nova and Cyborg need to interact in many areas for handling instances with
accelerators. While this spec covers the gamut, specific areas are covered in
detail in other specs. We list all the areas below, identify which specific
parts are covered by other specs, and describe what is covered in this spec.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Representation: Cyborg shall represent devices as nested resource providers
under the compute node (except possibly for disaggregated servers),
accelerator types as resource classes and accelerators as inventory in
Placement. The properties needed for scheduling are represented as traits.
This is specified by &lt;a class="footnote-reference brackets" href="#cy-nova-place" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This spec does not
dwell on this topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discovery and Updates: Among the devices discovered in a host, Cyborg
intends to claim only those that are not included under the PCI Whitelisting
mechanism. Cyborg shall update Placement in a way that is compatible with
the virt driver’s update of Placement. These aspects are addressed in
sections &lt;a class="reference internal" href="#coexistence-with-pci-whitelists"&gt;Coexistence with PCI whitelists&lt;/a&gt; and &lt;a class="reference internal" href="#placement-update"&gt;Placement update&lt;/a&gt;
respectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User requests for accelerators: Users usually request compute resources via
flavors. However, since the requests for devices may be highly varied,
placing them in flavors may result in flavor explosion. We avoid that by
expressing device requests in a device profile &lt;a class="footnote-reference brackets" href="#dev-prof" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; . The
relationship between device profiles and flavors is explored in Section
&lt;a class="reference internal" href="#user-requests"&gt;User requests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When an instance creation (boot) request is made, the contents of a device
profile shall be translated to request groups in the request spec; the
syntax in request groups is covered in Section &lt;a class="reference internal" href="#updating-the-request-spec"&gt;Updating the Request Spec&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance scheduling: Nova shall use the Placement data populated by Cyborg
to schedule instances. This spec does not dwell on this topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assignment of accelerators: We introduce the concept of Accelerator Request
objects in Section &lt;a class="reference internal" href="#accelerator-requests"&gt;Accelerator Requests&lt;/a&gt;.  The workflow to create and use
them is summarized in Section &lt;a class="reference internal" href="#nova-changes-for-assignment-workflow"&gt;Nova changes for Assignment workflow&lt;/a&gt;. The
same section also highlights the Nova changes needed. The details of the
Cyborg API implementation for this workflow is covered in Cyborg specs
(&lt;a class="footnote-reference brackets" href="#cy-api-impl" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance operations: The behavior with respect to accelerators for all
standard instance operations are defined in &lt;a class="footnote-reference brackets" href="#inst-ops" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.
This spec does not dwell on this topic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A user requests an instance with one or more accelerators of different
types assigned to it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An operator may provide users with both Device as a Service or
Accelerated Function as a Service in the same cluster (see
&lt;a class="footnote-reference brackets" href="#cy-nova-place" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following use cases are not addressed in Train but are of long term
interest:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A user requests to add one or more accelerators to an existing instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live migration with accelerators.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="coexistence-with-pci-whitelists"&gt;
&lt;h3&gt;Coexistence with PCI whitelists&lt;/h3&gt;
&lt;p&gt;The operator tells Nova which PCI devices to claim and use by configuring the
PCI Whitelists mechanism. In addition, the operator installs Cyborg drivers in
compute nodes and configures/enables them. Those drivers may then discover and
report some PCI devices. The operator must ensure that both configurations
are compatible.&lt;/p&gt;
&lt;p&gt;Ideally, there should be a single way for the operator to identify which PCI
devices should be claimed by Nova and which by Cyborg. This could be along the
lines suggested in &lt;a class="footnote-reference brackets" href="#generic-dev-disc" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; or &lt;a class="footnote-reference brackets" href="#kosamara" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. If such a mechanism
could be agreed upon by all stakeholders, Cyborg could adopt it.&lt;/p&gt;
&lt;p&gt;Until that point, the operator tells Cyborg which devices to claim by
using Cyborg’s configuration file. The operator must ensure that this is
compatible with the PCI whitelists configured in Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="placement-update"&gt;
&lt;h3&gt;Placement update&lt;/h3&gt;
&lt;p&gt;Cyborg shall call Placement API directly to represent devices and
accelerators. Some of the intended use cases for the API invocation are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create or delete child RPs under the compute node RP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create or delete custom RCs and custom traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Associate traits with RPs or remove such association.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update RP inventory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cyborg shall not modify the RPs created by any other component, such
as Nova virt drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="user-requests"&gt;
&lt;h3&gt;User requests&lt;/h3&gt;
&lt;p&gt;The user request for accelerators is encapsulated in a device profile
&lt;a class="footnote-reference brackets" href="#dev-prof" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, which is created and managed by the admin via the Cyborg API.&lt;/p&gt;
&lt;p&gt;A device profile may be viewed as a ‘flavor for devices’. Accordingly, the
instance request should include both a flavor and a device profile. However,
that requires a change to the Nova API for instance creation. To mitigate the
impact of such changes on users and operators, we propose to do this
in phases.&lt;/p&gt;
&lt;p&gt;In the initial phase, Nova API remains as today. The device profile is folded
into the flavor as an extra spec by the operator, as below:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="s1"&gt;'accel:device_profile=&amp;lt;profile_name&amp;gt;'&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Thus the standard Nova API can be used to create an instance with only the
flavor (without device profiles), like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;....&lt;/span&gt;  &lt;span class="c1"&gt;# instance creation&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the future, device profile may be used by itself to specify accelerator
resources for the instance creation API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="updating-the-request-spec"&gt;
&lt;h3&gt;Updating the Request Spec&lt;/h3&gt;
&lt;p&gt;When the user submits a request to create an instance, as described in Section
&lt;a class="reference internal" href="#user-requests"&gt;User requests&lt;/a&gt;, Nova needs to call a Cyborg API, to get back the resource
request groups in the device profile and merge them into the request spec.
(This is along the lines of the scheme proposed for Neutron
&lt;a class="footnote-reference brackets" href="#req-spec-groups" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.)&lt;/p&gt;
&lt;p id="cyborg-client-module"&gt;This call, like all the others that Nova would make to Cyborg APIs, is done
through a Keystone-based adapter that would locate the Cyborg service, similar
to the way Nova calls Placement. A new Cyborg client module shall be added to
Nova, to encapsulate such calls and to provide Cyborg-specific functionality.&lt;/p&gt;
&lt;p&gt;VM images in Glance may be associated with image properties (other than image
traits), such as bitstream/function IDs needed for that image. So, Nova should
pass the VM image UUID from the request spec to Cyborg. This is TBD.&lt;/p&gt;
&lt;p&gt;The groups in the device profile are numbered by Cyborg. The request groups
that are merged into the request spec are numbered by Nova. These numberings
would not be the same in general, i.e., the N-th device profile group may not
correspond to the N-th request group in the request spec.&lt;/p&gt;
&lt;p&gt;When the device profile request groups are added to other request groups in
the flavor, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_policy&lt;/span&gt;&lt;/code&gt; of the flavor shall govern the overall
semantics of all request groups.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="accelerator-requests"&gt;
&lt;h3&gt;Accelerator Requests&lt;/h3&gt;
&lt;p&gt;An accelerator request (ARQ) is an object that represents
the state of the request for an accelerator to be assigned to an instance.
The creation and management of ARQs are handled by Cyborg, and ARQs are
persisted in Cyborg database.&lt;/p&gt;
&lt;p&gt;An ARQ, by definition, represents a request for a single accelerator. The
device profile in the user request may have N request groups, each asking for
M accelerators; then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;N&lt;/span&gt; &lt;span class="pre"&gt;*&lt;/span&gt; &lt;span class="pre"&gt;M&lt;/span&gt;&lt;/code&gt; ARQs will be created for that device profile.&lt;/p&gt;
&lt;p&gt;When an ARQ is initially created by Cyborg, it is not yet associated with a
specific host name or a device resource provider. So it is said to be in an
unbound state. Subsequently, Nova calls Cyborg to bind the ARQ to a host name,
a device RP UUID and an instance UUID. If the instance fails to spawn, Nova
would unbind the ARQ without deleting it. On instance termination, Nova would
delete the ARQs after unbinding them.&lt;/p&gt;
&lt;p id="match-rp"&gt;Each ARQ needs to be matched to the specific RP in the allocation candidate
that Nova has chosen, before the ARQ is bound. Since Placement does not match
RPs to request groups, this must be done in the Cyborg client module of Nova
(&lt;a class="reference internal" href="#cyborg-client-module"&gt;cyborg-client-module&lt;/a&gt;). The matching is done using the requester_id field
in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; object (&lt;a class="footnote-reference brackets" href="#requester-id" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;) as below:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The order of request groups in a device profile is not significant, but it
is preserved by Cyborg. Thus, each device profile request group has a unique
index.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the device profile request groups returned by Cyborg are added to the
request spec, the requester_id field is set to ‘device_profile_&amp;lt;N&amp;gt;’ for the
N-th device profile request group (starting from zero). The device profile
name need not be included here because there is only one device profile per
request spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When Cyborg creates an ARQ for a device profile, it embeds the device
profile request group index in the ARQ before returning it to Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The matching is done in two steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each ARQ is mapped to a specific request group in the request spec using
the requester_id field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each request group is mapped to a specific RP using the same logic as the
Neutron bandwidth provider (&lt;a class="footnote-reference brackets" href="#map-rg-to-rp" id="id11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="nova-changes-for-assignment-workflow"&gt;
&lt;h3&gt;Nova changes for Assignment workflow&lt;/h3&gt;
&lt;p&gt;This section summarizes the workflow details for Phase 1. The changes needed
in Nova are marked with NEW.&lt;/p&gt;
&lt;p&gt;NEW: A Cyborg client module is added to nova (&lt;a class="reference internal" href="#cyborg-client-module"&gt;cyborg-client-module&lt;/a&gt;). All
Cyborg API calls are routed through that.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;The Nova API server receives a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API request with a flavor
that includes a device profile name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova API server calls the Cyborg API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/v2/device_profiles?name=$device_profile_name&lt;/span&gt;&lt;/code&gt; and gets back the device
profile request groups. These are added to the request spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Nova scheduler invokes Placement and gets a list of allocation
candidates. It selects one of those candidates and makes
claim(s) in Placement. The Nova conductor then sends a RPC message
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;build_and_run_instances&lt;/span&gt;&lt;/code&gt; to the Nova compute manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: Nova calls the Cyborg API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/v2/accelerator_requests&lt;/span&gt;&lt;/code&gt; with the
device profile name. Cyborg creates a set of unbound ARQs for that device
profile and returns them to Nova. (The call may originate from Nova
conductor or the compute manager; that will be settled in code review.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Cyborg client in Nova matches each ARQ to the resource provider
picked for that accelerator. See &lt;a class="reference internal" href="#match-rp"&gt;match-rp&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova compute manager calls the Cyborg API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATCH&lt;/span&gt;
&lt;span class="pre"&gt;/v2/accelerator_requests&lt;/span&gt;&lt;/code&gt; to bind the ARQ with the host name, device’s RP
UUID and instance UUID. This is an asynchronous call which prepares or
reconfigures the device in the background.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: Cyborg, on completion of the bindings (successfully or otherwise),
calls Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/os-server-external-events&lt;/span&gt;&lt;/code&gt; API with:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
   "events": [
      { "name": "arq_resolved",
        "tag": $arq_uuid,
        "server_uuid": $instane_uuid,
        "status": "ok" # or "failed"
      },
      ...
   ]
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova virt driver waits for the notification, subject to the
timeout mentioned in Section &lt;a class="reference internal" href="#other-deployer-impact"&gt;Other deployer impact&lt;/a&gt;. It then calls
the Cyborg REST API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/v2/accelerator_requests?instance=&amp;lt;uuid&amp;gt;&amp;amp;bind_state=resolved&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: The Nova virt driver uses the attach handles returned from the Cyborg
call to compose PCI passthrough devices into the VM’s definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NEW: If there is any error after binding has been initiated, Nova
must unbind the relevant ARQs by calling Cyborg API. It may then retry on
another host or delete the (unbound) ARQs for the instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This flow is captured by the following sequence diagram, in which the Nova
conductor and scheduler are together represented as the Nova controller. The
ARQ creation is shown to happen in Nova compute manager only for concreteness;
it may be in the controller instead.&lt;/p&gt;
&lt;img alt="../../../_images/nova-cyborg-interaction.svg" src="../../../_images/nova-cyborg-interaction.svg"/&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;It is possible to have an external agent create ARQs from device profiles
by calling Cyborg, and then feed those pre-created ARQs to the Nova instance
creation API, analogous to Neutron ports. We do not take that approach yet
because it requires changes to Nova instance creation API.&lt;/p&gt;
&lt;p&gt;It is possible to have the Nova virt driver poll for the Cyborg ARQ binding
completion. That is not preferable, partly because that is not the pattern of
interaction with other services like Neutron.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None. A new extra_spec key &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accel:device_profile_name&lt;/span&gt;&lt;/code&gt; is added to
the flavor.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Nova may choose to add additional notifications for Cyborg API calls.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The extra calls to Cyborg REST API may potentially impact Nova
conductor/scheduler throughput. This has been mitigated by making some
critical Cyborg operations as asynchronous tasks.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The deployer needs to set up the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;clouds.yaml&lt;/span&gt;&lt;/code&gt; file so that Nova
can call the Cyborg REST API.&lt;/p&gt;
&lt;p&gt;The deployer needs to configure a new tunable in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-cpu.conf&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arq_binding_timeout&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;
  &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Cyborg&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;ARQ&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;fatal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;aborted&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;300.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Define two new standard resource classes: FPGA and PGPU.&lt;/p&gt;
&lt;p&gt;We have VGPU and VGPU_DISPLAY_HEAD RCs defined already. But we propose a
PGPU as a different RC for the following reasons:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Both VGPU and VGPU_DISPLAY_HEAD RCs specifically refer to virtual GPUs.
We need a different one for physical GPUs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will be subject to separate quotas/limits in Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using PCI_DEVICE RC is too general: we want quotas for GPU RC
specifically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Sundar Nadathur&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;See the steps marked NEW in &lt;a class="reference internal" href="#nova-changes-for-assignment-workflow"&gt;Nova changes for Assignment workflow&lt;/a&gt; section.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for device profiles &lt;a class="footnote-reference brackets" href="#dev-prof" id="id12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cyborg API specification &lt;a class="footnote-reference brackets" href="#cy-api" id="id13" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;10&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;There need to be unit tests and functional tests for the Nova changes.
Specifically, there needs to be a functional test fixture that mocks the
Cyborg API calls.&lt;/p&gt;
&lt;p&gt;There need to be tempest tests for the end-to-end flow, including failure
modes. The tempest tests should be targeted at a fake driver (in addition to
real hardware, if any) and tied to the Nova Zuul gate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Device profile creation needs to be documented in Cyborg, as noted in
&lt;a class="footnote-reference brackets" href="#dev-prof" id="id14" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The need for operator to fold the device profile into the flavor needs to be
documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="cy-nova-place" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/603545/"&gt;Specification for Cyborg Nova Placement
interaction&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="dev-prof" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id12"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id14"&gt;4&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/602978"&gt;Device profiles specification&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="cy-api-impl" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/608624/"&gt;Specification for Cyborg API implementation&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="inst-ops" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/605237/"&gt;Specification for instance operations with accelerators&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="generic-dev-disc" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/603805/"&gt;Generic device discovery&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="kosamara" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/591037/"&gt;Modelling passthrough devices for report to placement&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="req-spec-groups" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/567267/"&gt;Store RequestGroup objects in RequestSpec&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="requester-id" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.openstack.org/cgit/openstack/nova/tree/nova/objects/request_spec.py?h=refs/changes/27/619527/16#n818/"&gt;Requester_id field in RequestGroup&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="map-rg-to-rp" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id11"&gt;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/616239/33/nova/objects/request_spec.py/"&gt;Map request groups to resource providers&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="cy-api" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id13"&gt;10&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/658263/"&gt;Specification for Cyborg API Version 2&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id15"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 05 Jul 2023 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store a symmetric key in the key manager. This
remains a long running piece of technical debt in the encrypted volume
implementation as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; does not directly encrypt data with the provided
key.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID.&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypt these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; imagebackend, both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]images_type&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt;
&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]use_cow_images&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; must be configured in order for
resize to work. This is also true without encryption but it may still be
helpful to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that a user must have policy permission to create secrets in
Barbican in order for encryption to work for that user. Secrets are created
in Barbican using the user’s auth token. Admins have permission to create
secrets in Barbican by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ephemeral-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/ephemeral-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 26 Jun 2023 00:00:00 </pubDate></item><item><title>Policy Service Role Default</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/policy-service-role-default.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/policy-service-role-default"&gt;https://blueprints.launchpad.net/nova/+spec/policy-service-role-default&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally all internal service-to-service APIs should not be accessible
by admin or end user by default. From policy defaults it should be
clear which APIs are supposed to be used by admin or end user and
which is for internal service-to-service APIs communication.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, internal service-to-service communication APIs have their
default policy as either admin or project roles which means operators
need to assign the admin or project roles to their service users.
That service user having admin or project role access is poor security
practice as they can perform admin or project level operations.&lt;/p&gt;
&lt;p&gt;Another problem is that APIs which are meant to only be used by internal
services are able to be called by regular users and human admins. Requiring
(and allowing only) a service role for these APIs help avoid intentional
and accidental abuse.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I want to keep &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user to access
service-to-service APIs with least privilege.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We need to make sure all the policy rules for internal service-to-service
APIs are default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role only. Example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:os-server-external-events:create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'role:service'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'project'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Keystone’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role is kept outside of the existing role hierarchy
that includes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader&lt;/span&gt;&lt;/code&gt;. Keeping the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
role outside the current hierarchy ensures we’re following the principle
of least privilege for service accounts.&lt;/p&gt;
&lt;p&gt;We need to make all the service-to-service APIs which are &lt;em&gt;only&lt;/em&gt; suitable
for services default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role only. But we might have some cases
where APIs are both intended for service usage, as well as admin (any other
user role) usage. For such policy rules we need to default them to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
as well as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; (or any other user role) role. For example,
‘role:admin or role:service’&lt;/p&gt;
&lt;p&gt;As Nova have dropped the system scope implementation, service-to-service
communication with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role will be done with project scope token
(which is currently done in devstack setup).&lt;/p&gt;
&lt;p&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:delete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-volumes-attachments:swap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-server-external-events:create&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep the service-to-service APIs default same as it is and expect operators
to take care of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role users access permissions by overriding
it in the policy.yaml.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:delete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-volumes-attachments:swap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-server-external-events:create&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Easier to understand service-to-service APIs policy and restricting them to
least privilege.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If service-to-service APIs are used by the admin or end user then make
sure to override the required permission in policy.yaml because by default
they will be accessed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New APIs must add policies that follow the new pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;If service-to-service APIs are used by the admin or end user then make
sure to override the required permission in policy.yaml because by default
they will be accessed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user only. If deployment
overrides these policies then, they need to start considering the new
default policy rules.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Modify the service-to-service APIs defaults&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify policy rule unit tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Modify or add the policy unit tests.&lt;/p&gt;
&lt;p&gt;Add a job enabling the new defaults and run the tempest tests to make sure
existing service-service APIs communication work fine. If needed modify the
token used by services as per the new defaults.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;API Reference should be updated to add all the service-service APIs under
separate section and mention about &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role as their default.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 28 Apr 2023 00:00:00 </pubDate></item><item><title>Use extend volume completion action</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/assisted-volume-extend.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend"&gt;https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume
action that has been proposed for Cinder in &lt;a class="footnote-reference brackets" href="#id12" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, to provide feedback on
success or failure when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server events.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many remotefs-based volume drivers in Cinder use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; &lt;span class="pre"&gt;resize&lt;/span&gt;&lt;/code&gt;
command to extend volume files.
However, when the volume is attached to a guest, QEMU will lock the file and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt;&lt;/code&gt; will be unable to resize it.&lt;/p&gt;
&lt;p&gt;In this case, only the QEMU process holding the lock can resize the volume,
which can be triggered through the QEMU monitor command &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is currently no adequate way for Cinder to use this feature, so the NFS,
NetApp NFS, Powerstore NFS, and Quobyte volume drivers all disable extending
attached volumes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I want to extend a NFS/NetApp NFS/Powerstore NFS/Quobyte volume
while it is attached to an instance and I want the volume size and status to
reflect the success or failure of the operation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova’s libvirt driver uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command when handling the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event, to inform QEMU that the size of an
attached volume has changed.
It is in principle also capable of extending a volume file, but is currently
unable to provide feedback to Cinder on the success of the operation.&lt;/p&gt;
&lt;p&gt;Currently, Cinder will send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event to
Nova only after it has finalized the extend operation and reset the volume
status from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;a class="footnote-reference brackets" href="#id12" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, Cinder will allow volume drivers to hold off finalizing the extend
operation and leave the volume status as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, until after it has
send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event and received feedback from Nova in form of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action, with an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; argument
indicating whether to finalize or to roll back the operation.&lt;/p&gt;
&lt;p&gt;This will currently affect only the volume drivers mentioned above, all of
which did not previously support online extend.
All other drivers will continue to send the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event after
finalizing the operation and resetting to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt; status, and will not
expect a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; volume action.&lt;/p&gt;
&lt;section id="compute-agent"&gt;
&lt;h3&gt;Compute Agent&lt;/h3&gt;
&lt;p&gt;Nova’s compute agent will use the volume status to differentiate between the
two behaviors when handling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the volume status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, then it will attempt to read
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; from the volume’s metadata and use this value as the
new size of the volume, instead of the volume size field.&lt;/p&gt;
&lt;p&gt;After successfully extending the volume, it will call the extend volume
completion action of the volume, with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;false&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If anything goes wrong, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; being missing from the
metadata, or being smaller than the current size of the volume, it will
log the error and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;, so Cinder can roll back the operation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For any other volume status, including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, the event will be handled
as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="api"&gt;
&lt;h3&gt;API&lt;/h3&gt;
&lt;p&gt;Nova’s API will introduce a new microversion, so that Cinder can make sure the
new behavior is available, before leaving an extend operation unfinished.&lt;/p&gt;
&lt;p&gt;To handle older compute agents during a rolling upgrade, the API will also
check the compute service version of the target agent when receiving a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event with the new microversion.
If a target compute agent is too old to support the feature, the API will
discard the event and call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; action with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"error":&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A previous change tried to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event
to support online extend for the NFS driver &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but did not rely on
feedback from Nova to Cinder at all.
Instead, it would just set the new size of the volume, change the status
back to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;, notify Nova, and hope for the best.&lt;/p&gt;
&lt;p&gt;If anything went wrong on Nova’s side, this would still result in a volume
state indicating that the operation was successful, which is not acceptable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A previous version of this spec proposed a new synchronous API in Nova &lt;a class="footnote-reference brackets" href="#id11" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;,
that would directly call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CompVirtAPI.extend_image&lt;/span&gt;&lt;/code&gt; of the nova-compute
instance managing the guest that a volume was attached to.
This API would provide a single mechanism to trigger the resize operation,
communicate the new size to Nova, and get feedback on the success of the
operation.&lt;/p&gt;
&lt;p&gt;The problem with a synchronous API is, that RPC and API timeouts limit the
maximum time an extend operation can take.
For QEMU, this seemed to be acceptable, because storage preallocation is
hard disabled for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block-resize&lt;/span&gt;&lt;/code&gt; command, and because all currently
plausible file systems support sparse file operations.&lt;/p&gt;
&lt;p&gt;However, this may not be true for other volume or virt drivers that might
require this API in the future.
It would also break with the established pattern of asynchronous
coordination between Nova and Cinder, which includes the assisted snapshot
and volume migration features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Following this pattern, we could make the proposed API asynchronous and use
a new callback in Cinder, similar to Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-assisted-volume-snapshots&lt;/span&gt;&lt;/code&gt;
API, which uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-update_snapshot_status&lt;/span&gt;&lt;/code&gt; snapshot action to provide
feedback to Cinder.&lt;/p&gt;
&lt;p&gt;The function of the new Nova API would then just be to trigger the operation
and to communicate the new size.
The question is then, whether that warrants adding a new API to Nova, since
there are existing mechanisms that could be used for either.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The existing mechanism for triggering the extend operation in Nova is of
course the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; external server event.
Using it for this purpose, as this spec proposes, requires the target size
to be transferred separately, because external server events only have a
single text field that is freely usable, which for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt;
is already used for the volume ID.&lt;/p&gt;
&lt;p&gt;Besides storing it in the admin metadata, as &lt;a class="footnote-reference brackets" href="#id12" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and this spec propose,
there is also the option of updating the size field of the volume, as &lt;a class="footnote-reference brackets" href="#id10" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
was essentially doing.&lt;/p&gt;
&lt;p&gt;This would require the volume size field to be reset on a failure.
If an error response from Nova was lost, the volume would just keep the new
size.
We would need to extend &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-reset_status&lt;/span&gt;&lt;/code&gt; to allow a size reset, or
something similar to clean up volumes like this.
This would be possible, but updating the size field only after the volume
was successfully extended seems like a cleaner solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could also extend the external server event API to accept additional data
for events, and use this to communicate the new size to Nova.&lt;/p&gt;
&lt;p&gt;This option was judged favorably by reviewers on the previous version of
this spec, &lt;a class="footnote-reference brackets" href="#id11" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but it would be a more complex change to the Nova API.&lt;/p&gt;
&lt;p&gt;However, if additional data fields become available in a future version of
the external server event API, it would be a relatively minor change to use
this instead of volume metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The behavior of the external server event API will change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If Nova receives a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event, and the referenced volume has
status of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;, Nova will look for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_new_size&lt;/span&gt;&lt;/code&gt; key in
the volume metadata, and use this instead of the volume size field as the
target size to update the block device mapping and to pass to the virt
driver’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_volume&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Nova will also attempt to call Cinder’s new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt;
volume action proposed in &lt;a class="footnote-reference brackets" href="#id12" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to let Cinder know if the operation was
successful or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, the API will behave as before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Checking the target compute service version allows the API to handle rolling
upgrades gracefully.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kgube&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None yet&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the external server event API to check the target compute service
version for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeVirtAPI.extend_volume&lt;/span&gt;&lt;/code&gt; method to follow the behavior
outlined in &lt;a class="reference internal" href="#compute-agent"&gt;Compute Agent&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt NFS job in the Nova gate to validate online extend.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The extend volume completion action &lt;a class="footnote-reference brackets" href="#id12" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We should test that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; gets called correctly
in all possible error or success condition if a volume has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt;
status.&lt;/p&gt;
&lt;p&gt;We should test the case that the call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend_volume_completion&lt;/span&gt;&lt;/code&gt; fails.&lt;/p&gt;
&lt;p&gt;We also need to test that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; continues to be handled correctly
for volumes not in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extending&lt;/span&gt;&lt;/code&gt; status.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new behavior of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume-extended&lt;/span&gt;&lt;/code&gt; event should be added to the
documentation of the external server event API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/739079"&gt;https://review.opendev.org/c/openstack/cinder/+/739079&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id4"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/855490/6"&gt;https://review.opendev.org/c/openstack/nova-specs/+/855490/6&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id9"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder-specs/+/866718"&gt;https://review.opendev.org/c/openstack/cinder-specs/+/866718&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id13"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>VNC console support for Ironic driver</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/ironic-vnc-console.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ironic-vnc-console"&gt;https://blueprints.launchpad.net/nova/+spec/ironic-vnc-console&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The feature aims at providing a vnc console from Ironic.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;End users often have to troubleshoot their instances because they might
have broken their boot configuration or locked themselves out with a
firewall. Keyboard-Video-Mouse (KVM) access is often required for
troubleshooting these types of issues as serial access is not always
available or correctly configured. Also, KVM provides a better user
experience as compared to serial console.&lt;/p&gt;
&lt;p&gt;Horizon’s VNC console is not supported for the ironic
nodes provisioned by Nova. This spec intends to extend that to
graphical console via the novnc proxy.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The end user will be able to get workable vnc console url from baremetal
server:
switch console type on bm side to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;baremetal&lt;/span&gt; &lt;span class="pre"&gt;node&lt;/span&gt; &lt;span class="pre"&gt;console&lt;/span&gt; &lt;span class="pre"&gt;enable&lt;/span&gt;&lt;/code&gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;console&lt;/span&gt; &lt;span class="pre"&gt;url&lt;/span&gt; &lt;span class="pre"&gt;show&lt;/span&gt; &lt;span class="pre"&gt;--novnc&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;nova_novncproxy should be deployed&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;the Ironic virt driver will have to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_vnc_console&lt;/span&gt;&lt;/code&gt; and return
a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ctype.ConsoleVNC&lt;/span&gt;&lt;/code&gt; with the required connection information
(port/ip). Will raise &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConsoleTypeUnavailable&lt;/span&gt;&lt;/code&gt; if vnc console
is unavailable for the instance.
To get the vnc console the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;node.get_console&lt;/span&gt;&lt;/code&gt; ironic API will be used (the
same API that is used for serial console).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Accept this limitation and only offer a serial console.
We can configure kvm access including access to the bios via the
serial proxy and shell in a box for nova provisioned ironic baremetal
instances.&lt;/p&gt;
&lt;p&gt;Use out-of-band KVM access provided by administrator without Ironic support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The VNC connection to the nodes are secured by a token generated while
creating the console in Nova.
This bearer token is the only thing required to connect to the proxy,
So the connection between user and proxy should be protected via ssl
the same as with vms&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;most changes will be on ironic side. In ironic we have to choose which
console will be used serial or vnc. This choice does not affect nova.
On ironic side also will be implemented vnc proxy, to handle rfb handshake&lt;/p&gt;
&lt;p&gt;additions to configs will be similar as for serial console:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-novncproxy/nova.conf&lt;/span&gt;&lt;/code&gt;:
[vnc]
novncproxy_host = …
novncproxy_port = …
server_listen = …
server_proxyclient_address = …
auth_schemes = vnc&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute-ironic/nova.conf&lt;/span&gt;&lt;/code&gt;:
[vnc]
enabled = true
novncproxy_host = …
novncproxy_port = …
server_listen = …
server_proxyclient_address = …
novncproxy_base_url = …&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-conductor/nova.conf&lt;/span&gt;&lt;/code&gt;
[vnc]
novncproxy_host = …
novncproxy_port = …
server_listen = …
server_proxyclient_address = …&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kirillgermanov&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;nova-compute-ironic: add new method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_vnc_console&lt;/span&gt;&lt;/code&gt; to Ironic virt
driver&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/ironic-specs/specs/not-implemented/vnc-graphical-console.html#id2"&gt;https://specs.openstack.org/openstack/ironic-specs/specs/not-implemented/vnc-graphical-console.html#id2&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add related unit test&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;update required&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/remote-console-access.html"&gt;https://docs.openstack.org/nova/latest/admin/remote-console-access.html&lt;/a&gt;
&lt;a class="reference external" href="https://docs.openstack.org/ironic/latest/admin/console.html"&gt;https://docs.openstack.org/ironic/latest/admin/console.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ironic-vnc-console"&gt;https://blueprints.launchpad.net/nova/+spec/ironic-vnc-console&lt;/a&gt;  - nova blueprint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/ironic/+/860689"&gt;https://review.opendev.org/c/openstack/ironic/+/860689&lt;/a&gt; - gerrit review ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/863177"&gt;https://review.opendev.org/c/openstack/nova/+/863177&lt;/a&gt; - gerrit review nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://stackoverflow.com/questions/16469487/vnc-des-authentication-algorithm"&gt;https://stackoverflow.com/questions/16469487/vnc-des-authentication-algorithm&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>Allow local scaphandre directory to be mapped to an instance using virtiofs</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/virtiofs-scaphandre.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virtiofs-scaphandre"&gt;https://blueprints.launchpad.net/nova/+spec/virtiofs-scaphandre&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Scaphandre is a tool that can be used to measure compute and VM power
consumption down to processes. (&lt;a class="reference external" href="https://github.com/hubblo-org/scaphandre"&gt;https://github.com/hubblo-org/scaphandre&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;If you want to know more, the BBC folks proposed an interesting use case
to create environmental dashboards:
&lt;a class="reference external" href="https://superuser.openstack.org/articles/environmental-reporting-dashboards-for-openstack-from-bbc-rd/"&gt;https://superuser.openstack.org/articles/environmental-reporting-dashboards-for-openstack-from-bbc-rd/&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, this is not possible to get consumption per VM as scaphandre
requires a directory on the compute node accessible into running VMs.
This directory contains data required by the scaphandre instance (guest agent)
running on the VM to correctly reports VM and VM associated processes
consumption.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://hubblo-org.github.io/scaphandre-documentation/how-to_guides/propagate-metrics-hypervisor-to-vm_qemu-kvm.html"&gt;Scaphandre proposed solution&lt;/a&gt; to get these data is to mount the directory
using virtiofs in the VM.
However, the user can not do that, as it requires the VM XML definition file
to be modified. Nova fully manages this file, and as a result, only nova
can change it.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user, I want to know the consumption of my compute node and drill
down to VM and VM processes individual consumption.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an administrator, I want to allow this usage but make sure the user
can mount only the configured required directory. I also want not to leak
cloud design insights.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To simplify specifications, the feature will be named
&lt;cite&gt;virtiofs-scaphandre&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Although this feature is implemented to support scaphandre, other tools
could require this need. So the implementation will try to be as generic
as possible.&lt;/p&gt;
&lt;p&gt;This change relies partially on
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/libvirt-virtiofs-attach-manila-shares.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/libvirt-virtiofs-attach-manila-shares.html&lt;/a&gt;
specification to build the VM XML file including virtiofs settings
(mostly &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/833090"&gt;driver part&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This implies the same requirements and limitation.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;=5.0 and libvirt &amp;gt;= 6.2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Associated instances use file backed memory or huge pages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live migrate an instance will not be supported as life attach and detach has
landed only “recently” in &lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1897708"&gt;libvirt&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Change description:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a compute configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_local_fs&lt;/span&gt;&lt;/code&gt; that specify mappings
between compute source directory and VMs destination &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;mount_tags&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;share_local_fs = { "/var/lib/libvirt/scaphandre": "scaphandre" }
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the above configuration option is present starting the compute
node, add a compute trait &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SHARE_LOCAL_FS&lt;/span&gt;&lt;/code&gt; specifying the
&lt;cite&gt;virtiofs-scaphandre&lt;/cite&gt; feature is available on this compute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users can add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:power_metrics&lt;/span&gt;&lt;/code&gt; as
extra specs or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_power_metrics&lt;/span&gt;&lt;/code&gt; image properties, and thus 2 things
will happen:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Nova will schedule the instance to a host that has share_local_fs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova will add the virtiofs settings in the instance XML file as specified
by the following example.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-xml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;&amp;lt;filesystem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'mount'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;accessmode=&lt;/span&gt;&lt;span class="s"&gt;'passthrough'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;driver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'virtiofs'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;'/var/lib/libvirt/scaphandre/&amp;lt;DOMAIN_NAME&amp;gt;'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;'mount_tag'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/filesystem&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &amp;lt;DOMAIN_NAME&amp;gt; is the name reported by &lt;cite&gt;virsh list&lt;/cite&gt;
or &lt;cite&gt;OS-EXT-SRV-ATTR:instance_name&lt;/cite&gt;.
This is the common name between qemu process that scaphandre use to get the
vm name and openstack.&lt;/p&gt;
&lt;p&gt;The instance name can be defined using the instance_name_template.
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#DEFAULT.instance_name_template"&gt;https://docs.openstack.org/nova/latest/configuration/config.html#DEFAULT.instance_name_template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;“OS-EXT-SRV-ATTR:instance_name”: “&lt;strong&gt;instance-00000034&lt;/strong&gt;”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/usr/bin/qemu-system-x86_64 -name &lt;strong&gt;guest=instance-00000034&lt;/strong&gt;…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a result, user will be able to mount the compute source directory on
his VM using the following command line.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;mount_tag&lt;span class="w"&gt; &lt;/span&gt;/var/scaphandre
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The user can see the mount_tag in the instance metadata. Mount automation
can be build based on this mechanism.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Introduce &lt;cite&gt;hw_powermetrics&lt;/cite&gt; image property as a new property object.&lt;/p&gt;
&lt;p&gt;Extend the flavor extra spec validation to check &lt;cite&gt;hw:power_metrics&lt;/cite&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The compute node filesystem will be shared read-only.
This is to prevent any modification on the host by VM users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The scaphandre installation and &lt;a class="reference external" href="https://hubblo-org.github.io/scaphandre-documentation/how-to_guides/propagate-metrics-hypervisor-to-vm_qemu-kvm.html"&gt;configuration&lt;/a&gt; on compute nodes is left
to the openstack administrator.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New configuration option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes to share the compute node filesystem if requested by an image
property or a flavor extra spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id6"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>Allowing target state for evacuate</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/implemented/allowing-target-state-for-evacuate.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/allowing-target-state-for-evacuate"&gt;https://blueprints.launchpad.net/nova/+spec/allowing-target-state-for-evacuate&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In certain circumstances the operator may desire to evacuate running
instances to stopped state regardless of the current state of the
instance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current evacuate instance API does not allow operators to set a
desired target state to the evacuated instances. Restoring the
original state of the instance when it was active on the source host
may result in issues if the guest required a valid token to be started
or prevent evacuation when using encrypted volumes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I would like to be able to evacuate instances to a
shut-off state because my tenant workloads may have specific
security requirements, that do not allow them to be started by the
administrator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I would like to be able to evacuate VMs with
encrypted volumes without making the barbican secret readable by
admins and reducing the security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user, if my instance is offline due to a host outage, I don’t
necessarily want an admin evacuating it and bringing it back online
without my knowledge as I may have already replaced it and the
zombie coming back may cause a conflict.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;As of the bumped version, the API will force the stopped state for
evacuated instances. It is expected that before the bumped version the
behavior stay the same, instances with state active or stopped will
keep their state at destination.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;With the new microversion nova will &lt;em&gt;always&lt;/em&gt; evacuate the instance
to SHUTOFF state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The only way to keep the instance state after the evacuation is to
use an older microversion.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It may be possible to enhance the API resetState to accept RUNNING and
SHUTOFF.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It may be possible to allow &lt;cite&gt;stop&lt;/cite&gt;’s action working with compute
node down, But that would have created incoherence between the
database and the real state of the instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A microversion bump is expected. But no changes in the schema will appear.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"evacuate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"b419863b7d814906a68fb31703c0dbd6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The nova api-ref will be updated to reflect the changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related to openstack client, nothing is expected to change instead
of a noop bump.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;It has been agreed that this spec would not resolve the design issue
whereby the &lt;cite&gt;evacuate server&lt;/cite&gt; action starts the virtual machines and
then stops it when the target state is stopped. An issue has been
reported at:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1994967"&gt;https://bugs.launchpad.net/nova/+bug/1994967&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Upgrade note will be added describing new behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An RPC change is expected to make the compute manager handle the new
target state, resulting in the version being incremented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At API level, a min version check will ensure that all services are
new enough to accept the request, if not the request will be
rejected with a NotSupported exception.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sahid-ferdjaoui&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API changes with microversion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing for the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit and functional testing for API change.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The api-ref will be updated to reflect the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=evacuate-server-evacuate-action-detail"&gt;https://docs.openstack.org/api-ref/compute/?expanded=evacuate-server-evacuate-action-detail&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 - Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;First introduction&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>Allow FQDN in hostname field</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/implemented/fqdn-in-hostname.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/fqdn-in-hostname"&gt;https://blueprints.launchpad.net/nova/+spec/fqdn-in-hostname&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enable end users to specify an FQDN as the instance hostname&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Originally when nova was created the instance hostname was set from the
instance display-name. Nova did not allow FQDNs in the display name and
explicitly blocked it, but that was later removed as a bugfix.&lt;/p&gt;
&lt;p&gt;Given the filtering of FQDN like strings was not done as a spec or feature
nova never provided an API guarantee that FQDNs can be used when creating a
server. After several bug reports of undesirable interactions with Designate
we decided to extend the normalization that removes non-ASCII alpha-numeric
character to also remove periods &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; from the hostname when
initializing it form the display name.&lt;/p&gt;
&lt;p&gt;In the Xena release we also introduced configurable instance hostnames by
exposing the hostname field directly in the API but maintained our
prohibition on FQDNs.
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/configurable-instance-hostnames.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/configurable-instance-hostnames.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec seeks to extend the hostname field to allow FQDNs to be used as the
hostname of an instance.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to allocate domains to my tenants and use automation to
validate that the VMs are created with an FQDN that is derived from that
domain.&lt;/p&gt;
&lt;p&gt;As a VNF vendor, I want to set the value of /etc/hostname to an FQDN
automatically when creating an instance via the api leveraging cloud-init
or another tool without using user-data.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;add a new api microversion to opt into using an FQDN in the hostname field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;increase the character length limit on the host name filed form 63 to 255&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove the rejection of “.” and other legal characters in a FQDN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;currently, attempting to use multi-create with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--hostname&lt;/span&gt;&lt;/code&gt; parameter
results in an error 400. This spec continues this behavior: multi-create with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--hostname&lt;/span&gt;&lt;/code&gt;, be it FQDN or short name, continues to be disallowed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;..NOTE:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;Today&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;propagated&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt;
&lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;With&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt;
&lt;span class="n"&gt;FQDN&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;also&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;propagated&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="n"&gt;without&lt;/span&gt; &lt;span class="n"&gt;alteration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Nova could add a FQDN field
e.g. openstack server create –FQDN …&lt;/p&gt;
&lt;p&gt;This raises ambiguity of when to use –hostname vs –FQDN and requires a
change to the data model to store the new field.&lt;/p&gt;
&lt;p&gt;Nova could add a domain field
e.g. openstack server create –hostname my-host –domain my.domain.com …&lt;/p&gt;
&lt;p&gt;This is better then –FQDN but still requires a db and object changes for
little benefit.&lt;/p&gt;
&lt;p&gt;Nova could try to propagate hostname changes to neutron ports and floating IPs.
This is seen as risky, complex and hard to understand.&lt;/p&gt;
&lt;p&gt;First if nova was to propagate hostname changes to the port dns_name field it
would only be able to do so on ports that were created by nova, not pre created
ports passed in by the API user. If we updated ports that were passed in
it could break existing use-cases where an end user set the desired name.&lt;/p&gt;
&lt;p&gt;Second the floating IP &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; is not typically the same as the instance
FQDN. The instance hostname or FQDN is typically an internal name used in the
application and the floating ip is used to expose a public name for the
service. i.e. the instance might be called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;webserver.cloud.com&lt;/span&gt;&lt;/code&gt; where
as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; of the floating IP might be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;blog.mysite.example.com&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Given the two reasons above, and the fact nova does not want to manage
networking, propagation of hostname changes to neutron ports is out of scope.&lt;/p&gt;
&lt;p&gt;Since this is only useful when using designate and designate already
monitors nova’s notification endpoint to update dns records using the
designate-sink component, this functionality can be implemented using designate
if designate desire in the future.&lt;/p&gt;
&lt;p&gt;For these reasons updating the hostname in other services, when its updated in
nova, is out of scope.&lt;/p&gt;
&lt;p&gt;..NOTE:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;As&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt;
&lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;drive&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ever&lt;/span&gt; &lt;span class="n"&gt;regenerated&lt;/span&gt; &lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;cross&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt;
&lt;span class="n"&gt;resize&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;guest&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;drive&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;does&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;behavior&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;before&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;The database field is already large enough to hold any valid FQDN so no changes
are required to the db. The instance object declares the hostname field as a
string and also requires no changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new API microversion will be introduced to allow FQDNs in the hostname field.
Minor changes will be required to conditionally change the length restriction
and disable some of the current validation when the new microversion is used
but the code will remain for older microversions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will be able to set the hostname of their vm to an FQDN, however without
using an external service like designate to advertise the FQDN it may not be
resolvable without manual intervention.&lt;/p&gt;
&lt;p&gt;Nova provides no guarantee of uniqueness or reachability of the FQDN provided
by the end user.&lt;/p&gt;
&lt;p&gt;As is the case today, nova will only set the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; on a neutron port
once when the server is first created. If the end user updates the
instance.hostname, it will be updated in the nova db and become visible in
the metadata API hostname field. It is out of scope of the nova project to
propagate this hostname change to any neutron ports, floating IPs or
dns records.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers should be aware that unique FQDNs or hostnames cannot be enforced
using the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]/osAPI_compute_unique_server_name_scope&lt;/span&gt;&lt;/code&gt;
config option as that provides uniqueness of the display name,
not the hostname.&lt;/p&gt;
&lt;p&gt;This spec does not introduce a way to force the hostnames or FQDNs
to be unique in any scope.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;osc should be extended to support the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;notartom&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;remove API restriction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update API sample tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;provide new microversion and API ref&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update osc&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be entirely tested with API/functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API ref will be updated&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>CPU state management in libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/implemented/libvirt-cpu-state-mgmt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-cpu-state-mgmt"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-cpu-state-mgmt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In many telecom or semi-static clouds, there is a bin packing problem
where a node for all practical use cases is full since no further
applications can be scheduled to the host but in reality, it still has
unused CPU cores.&lt;/p&gt;
&lt;p&gt;In a typical server system, an idle CPU core consumes 3-5 watts of
power and produces 3-5 watts of heat which the data center cooling
solution must accommodate. To facilitate reducing power usage and heat
output in order to make data centers greener and less expensive, it makes sense
to allow the power state of CPUs to be turned off or using another governor so
that they can be optimized.&lt;/p&gt;
&lt;p&gt;An easy possibility is to have the libvirt driver to support it by modifying
power states from the kernel sysfs interface.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;For our large telco operators, they often find that they have 2-4 CPUs that are
not usable due to CPU pinning/packing requirements per host. Each CPU
consumes 3-5 watts per core or ~12-20 watts per host. Assuming a nominal
cost per kWh of $0,20 and 1000 hosts, that means they pay $35,040 in wasted
electricity a year alone from just the idle CPU usage plus the additional cost
of dissipating all of the heat generated.&lt;/p&gt;
&lt;p&gt;Furthermore, while many telco use-cases require low latency and high
throughput, not all of them require the CPU to run at the max frequency.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator using the nova libvirt driver, I would like to be able
to disable or run slower cpu cores using the kernel sysfs interface.&lt;/p&gt;
&lt;p&gt;As an operator, I want my nova-compute service to enable or put at max
performance a CPU core if it will be in use for a new instance that is
currently starting.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;There are two parts to this proposal :&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;add a config option for declaring that CPUs are managed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add a config option for telling the performance strategy to use&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="declaring-cpus-as-managed"&gt;
&lt;h3&gt;Declaring CPUs as managed&lt;/h3&gt;
&lt;p&gt;We can add a config option to the hardware section to declare that the host
CPUs are managed &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/821228"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# registered in group [libvirt]&lt;/span&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoolOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cpu_power_management'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Use libvirt to manage CPU cores performance.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If this option is set to True, then at nova-compute startup, all the CPUs that
are defined by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]/cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; option as dedicated will be
tuned for minimum performance (either offlined or set to powersave) depending
on the other CPU tuning configuration option explained below, but only if they
don’t run an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Of course, shared CPUs wouldn’t have their performance to be modified
as instances float between them. If we would like to support them
too, then &lt;em&gt;all&lt;/em&gt; CPU shared cores should be modified at the same time
and once an instance is arriving, then &lt;em&gt;all&lt;/em&gt; of them would need to
have the max performance.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="define-the-performance-strategy-per-compute-service"&gt;
&lt;h3&gt;Define the performance strategy per compute service&lt;/h3&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;for the sake of simplicity, here we loudly state that the performance
strategy will be defined against all CPU cores from the host, and
explicitely not be defined per CPU core.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Since different performance strategies could be taken per operator, we let them
decide which one they prefer per compute service. The current list of
performance strategies will be :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;online/offline CPU cores&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;flip between &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;performance&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;powersave&lt;/span&gt;&lt;/code&gt; CPU core governors&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The initial implementation won’t propose any other strategy (like reducing the
CPU clock) and we don’t expect those other strategies to be implemented in a
foreseeable future.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is the operator’s responsibility to verify that the OS kernel is
recent enough to support CPU core tuning and that those CPU cores
have their governors supporting both the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;performance&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;powersave&lt;/span&gt;&lt;/code&gt; profiles.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A configuration option will accordingly be defined for choosing between those
two strategies :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# registered in group [libvirt]&lt;/span&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cpu_power_management_strategy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'cpu_state'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'governor'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
           &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cpu_state'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Tuning strategy to reduce CPU power consumption when '&lt;/span&gt;
                &lt;span class="s1"&gt;'unused'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Two specific config options will be defined for telling which governors to
use.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# registered in group [libvirt]&lt;/span&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cpu_power_governor_low'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'powersave'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Governor to use in order to reduce CPU power consumption'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cpu_power_governor_high'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'performance'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Governor to use in order to have best CPU performance'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="instance-lifecycle"&gt;
&lt;h3&gt;Instance lifecycle&lt;/h3&gt;
&lt;p&gt;When an instance is spawned (or migrated or resumed), we will use the
performance strategy to either online the core or use the best governor.
When an instance is stopped (or powered off or suspended or shelved offload or
in confirm-resize state on the source host), then we would either offline the
core or use the powersaving governor.&lt;/p&gt;
&lt;p&gt;Note that even if we say that this is the operator responsibility to verify
whether their compute kernels support the two above strategies, we will return
an exception if when trying to either online the core or modify the governor,
so the instance could eventually be on the ERROR state.
Also, if we can’t offline (or powersave) the CPU core when we stop the
instance, then we would provide a WARNING log in the compute logs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could just do the first step and provide a way to disable checking the CPU
online state in the libvirt driver with no synchronization, but this would
require the operators to statically manage their cloud, which is cumbersome.&lt;/p&gt;
&lt;p&gt;We could do this directly in nova and amend Nova everytime we want a new
usecase. Not sure we’d appreciate this.&lt;/p&gt;
&lt;p&gt;We could make reporting CPUs to the Placement API controlable via config, but
this would only solve one usecase and would still require some tooling for
playing with the config option.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None, config defaults disable this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bauzas&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a config option for cpu state management &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/821228"&gt;[1]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a config option for cpu tuning&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;provide a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu&lt;/span&gt;&lt;/code&gt; framework for managing cpu core tuning thru sysfs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;modify libvirt to online/performance a CPU core when an instance is spawning&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;modify libvirt to offline/powersave a CPU core when an instance is stopped&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amend init_host() to put CPU cores to low performance (or offline)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Testing of this spec will be done with unit and functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Well, usual bits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>Add configuration options to set SPICE compression settings</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/implemented/nova-support-spice-compression-algorithm.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-support-spice-compression-algorithm"&gt;https://blueprints.launchpad.net/nova/+spec/nova-support-spice-compression-algorithm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes to add SPICE-related options to a Nova configuration.
These options can be used to enable and set the SPICE compression settings for
libvirt (QEMU/KVM) provisioned instances. Note that those options are only
taken into account if SPICE support is enabled (and the VNC support is
disabled).&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Sometimes, network bandwidth is limited especially if physical network hardware
is involved in an OpenStack setup, e.g. if old network switches with limited
uplink bandwidth are used. Nevertheless, a data-intensive transfer of console
data between compute nodes and remote console clients should be possible in
such an infrastructure. Here it would be beneficial if builtin compression
settings could be activated for transport protocols (currently only SPICE) in
order to transmit graphic-intense desktop content in networks with limited
bandwidth while gaining an acceptable quality of experience (QoE).&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An operator should be able to decide how to configure a desktop (console)
transport via SPICE. In particular, he should be able to configure the SPICE
compression algorithms and modes in order to&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;lower network bandwidth for graphical console accesses from (remote)
networks with limited bandwidth. Users can benefit from such a
configuration especially if they access a graphical console of an
instance from home.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;completely turn off default compression settings for local console
accesses while keeping latency as low as possible within a local (wired)
network. Such a configuration can be useful if users should only have
local access to graphical instances for visualizing computation results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;select an appropriate SPICE video detection/streaming for graphic-intense
use cases such as office work, media editing, and visualization of
computation results, depending on the available network bandwidth and the
QoE to be achieved.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user should be able to access the graphical console of an instance from
Horizon’s built-in spice-html5 client as before, even from (remote) networks
with limited bandwidth (e.g. from home).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to add configuration options for all transport protocols in
OpenStack that support the explicit activation of builtin compression settings.
Currently only the integrated SPICE protocol allows the activation of various
image &lt;a class="footnote-reference brackets" href="#id4" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and video &lt;a class="footnote-reference brackets" href="#id5" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; compression settings to lower the network bandwidth
while improving data transmission for graphic-intense desktops. Since SPICE is
only supported by the libvirt hypervisor (through the QEMU backend), all other
hypervisors and transport protocols are not affected by this proposed change.
Libvirt already provides an automatic configuration of SPICE-related
compression settings for the QEMU backend (see the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spice&lt;/span&gt;&lt;/code&gt; documentation in
the libvirt XML domain documentation &lt;a class="footnote-reference brackets" href="#id6" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;). Therefore, the change only requires
to make the libvirt hypervisor driver capable to generate a valid libvirt XML
config with activated SPICE compression settings. The OpenStack configuration
for the config generation should be stored in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spice&lt;/span&gt;&lt;/code&gt; configuration group
of a Nova configuration. This configuration group should be extended with
configuration options that are capable of specifying the SPICE-related
compression settings (choose compression algorithms and toggle compression
modes on/off).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The following SPICE-related options will be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spice&lt;/span&gt;&lt;/code&gt;
configuration group of a Nova configuration:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_compression&lt;/span&gt;&lt;/code&gt; = [ &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auto_glz&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auto_lz&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quic&lt;/span&gt;&lt;/code&gt; |
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glz&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;lz&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;off&lt;/span&gt;&lt;/code&gt; ];&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;jpeg_compression&lt;/span&gt;&lt;/code&gt; = [ &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auto&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;never&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;always&lt;/span&gt;&lt;/code&gt; ];&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;zlib_compression&lt;/span&gt;&lt;/code&gt; = [ &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auto&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;never&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;always&lt;/span&gt;&lt;/code&gt; ];&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;playback_compression&lt;/span&gt;&lt;/code&gt; = [ &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; ];&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;streaming_mode&lt;/span&gt;&lt;/code&gt; = [ &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all&lt;/span&gt;&lt;/code&gt; | &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;off&lt;/span&gt;&lt;/code&gt; ];&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each configuration option is optional and can be set explictly to configure the
associated SPICE compression setting for libvirt. If all configuration options
are not set, then none of the SPICE compression settings will be configured for
libvirt, which corresponds to the behavior before this proposed change. In this
case, the built-in defaults from the libvirt backend (e.g. QEMU) are used.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bahnwaerter&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add SPICE-related configuration options to the Nova configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create documentation for the SPICE-related configuration options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend the SPICE config generation in the libvirt hypervisor driver.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement unit tests for each function to cover testing of added and changed
methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend the Nova configuration documentation and add documentation for the
SPICE-related compression settings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;SPICE image compression:
&lt;a class="reference external" href="https://www.spice-space.org/spice-user-manual.html#_image_compression"&gt;https://www.spice-space.org/spice-user-manual.html#_image_compression&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;SPICE video compression:
&lt;a class="reference external" href="https://www.spice-space.org/spice-user-manual.html#_video_compression"&gt;https://www.spice-space.org/spice-user-manual.html#_video_compression&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;libvirt Domain XML format:
&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#graphical-framebuffers"&gt;https://libvirt.org/formatdomain.html#graphical-framebuffers&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>PCI Device Tracking In Placement</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/implemented/pci-device-tracking-in-placement.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pci-device-tracking-in-placement"&gt;https://blueprints.launchpad.net/nova/+spec/pci-device-tracking-in-placement&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The OpenStack Placement service was designed to provide tracking
of quantitative resources via resource class inventories and qualitative
characteristics via traits. Over the last few cycles, nova has utilized
Placement to track basic resources such as CPUs, RAM, and disk, and more
complex resources such as Virtual GPUs. This spec describes how Nova can
utilize Placement to track generic PCI devices without going into the details
of the NUMA awareness of such devices.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova has supported generic stateless PCI passthrough for many releases using a
dedicated PCI tracker in conjunction with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; scheduler
post filter.&lt;/p&gt;
&lt;p&gt;The PCI tracker is responsible for tracking which PCI devices are available,
claimed, and allocated, the capabilities of the device, its consumer when
claimed or allocated as well as the type of PCI device and location.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; is responsible for ensuring that devices,
requested by the VM, exist on a host during scheduling. These PCI requests come
from two sources: flavor-based PCI requests that are generated using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough:alias&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/extra-specs.html#pci_passthrough:alias"&gt;flavor extra specs&lt;/a&gt; and neutron based PCI requests
generated from SR-IOV backed neutron ports.&lt;/p&gt;
&lt;p&gt;While the current approach to PCI tracking works there are some limitations
in the current design and there is room for optimization.&lt;/p&gt;
&lt;p class="rubric"&gt;Limitations&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;During server creation PCI devices are not claimed until the instance_claim
is created on the compute node. As a result, it is possible for two
concurrent server create requests to race for the last device on a host
resulting in re-schedules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While Nova today tracks the capabilities of network interfaces in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_devices&lt;/span&gt;&lt;/code&gt; table and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; could match on those capabilities there is no
user-facing way to express a request for an SR-IOV neutron port with a
specific network capability e.g. TSO.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no admin-facing interface to check the available and allocated PCI
resources in the cloud. The only way is to look into the Nova database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Optimizations&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Today when the virt driver is assigning a PCI device on the compute hosts
it needs to look at all available PCI devices on the host and select one that
fulfills the PCI and NUMA requirements. If we model PCI devices in Placement
we only need to consider the devices associated with the PCI resource
allocation in Placement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Today when we schedule we perform host filtering of viable hosts based on
PCI devices in python. By utilizing Placement we can move that filtering to
SQL.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want instance creation to atomically claim resources to
decrease the chance of retries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to shorten the time it takes to select a host by
running fewer filters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to utilize traits and resource classes to model
PCI aliases and requests for more expressive device management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to be able to associate quotas with PCI device usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to be able to use the Placement API to query available
and allocated PCI devices in my cloud.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Device quotas would require unified limits to be implemented. Implementing
quotas is out of the scope of this spec beyond enabling the use case by
modeling PCI devices in Placement.&lt;/p&gt;
&lt;p&gt;This spec will also only focus on flavor-based PCI passthrough. Neutron
SR-IOV port will be addressed in a follow-up spec to limit the scope.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;The inventory tracking and allocation healing part of this feature already
been implemented in the Zed release. Still this spec contains the
description of the already implemented parts as well to server as context.
The specification of the missing pieces starts at &lt;a class="reference internal" href="#scheduling"&gt;Scheduling&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="opt-in-reporting-of-pci-devices-in-placement"&gt;
&lt;h3&gt;Opt-in reporting of PCI devices in Placement&lt;/h3&gt;
&lt;p&gt;To support upgrade of existing deployments with PCI passthrough configured
and to be able to deprecate and eventually remove some of the functionality of
the current PCI device tracker the new Placement based PCI device tracking will
be disabled by default in the first release. The new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; config option can be used to enable the
functionality. It will be defaulted to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; first and once it is turned to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; nova-compute will refuse to start if disabled again. In a future
release, after the PCI tracking in Placement is feature complete, the default
will be changed to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="pci-device-spec-configuration"&gt;
&lt;h3&gt;PCI device_spec configuration&lt;/h3&gt;
&lt;p&gt;Below we propose a change to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; configuration
option. While we are making this change we will take this opportunity to
update the name of the configuration option. The old name of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; config option will be deprecated for eventual
removal and a new name &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; will be added. Both the
old and the new name will support the newly proposed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;p&gt;The syntax of the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#pci.passthrough_whitelist"&gt;PCI passthrough device list&lt;/a&gt; configuration option will be
extended to support two additional standard tags &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt;. These new tags will only take effect if the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; config option is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-js notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nx"&gt;device_spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"vendor_id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1002"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"67FF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"resource_class"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_GPU"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"traits"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_RADEON_RX_560"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_GDDR5"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;device_spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:82:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"resource_class"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_FPGA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"traits"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_XILINX_XC7VX690T"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; tag will be accepted only when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt;
tag is not defined and will enable a PCI device to be associated with a custom
resource class. Each PCI device_spec entry may have at most one resource class
associated with it. Devices that have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag will not be
reported in Placement at this time as Neutron based SR-IOV is out of the
scope of the current spec.&lt;/p&gt;
&lt;p&gt;Where a PCI device does not have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; or a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt;
tag present it will be reported with a generated custom resource class.
The resource class will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PCI_&amp;lt;vendor_id&amp;gt;_&amp;lt;product_id&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag will be a comma-separated list of standard or custom trait
names that will be reported for the device RP in Placement.&lt;/p&gt;
&lt;p&gt;Nova will normalize and prefix the resource class and trait names with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_&lt;/span&gt;&lt;/code&gt;, if it isn’t already prefixed, before creating them in Placement.
Nova will first check the provided trait name in os_traits and if it exists
as a standard trait then that will be used instead of creating a custom one.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Initially traits will only be additive, in the future if we need to we can
allow traits to be removed using a +/- syntax but this is not included
in the scope of this spec.&lt;/p&gt;
&lt;p&gt;As detailed in the &lt;a class="reference internal" href="#modeling-pci-devices-in-placement"&gt;Modeling PCI devices in Placement&lt;/a&gt; section, each
physical device (PF) will be its own resource provider with inventories of
the relevant PF and VF resource classes. As such traits cannot vary per VF
device under the same parent PF. If VFs are individually matched by different
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entries, then defining different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt;  for different
VFs under the same PF is a configuration error and will be rejected.&lt;/p&gt;
&lt;p&gt;While it would possible to support defining different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt;
names for different VFs under the same parent PF, this is considered bad
practice and unnecessary complexity. Such configuration will be rejected.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Nova will detect if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; configuration of
an already reported device is changed at a nova-compute service restart. If
the affected device is free then Nova will apply the change in Placement. If
the device is allocated then changing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; would result in
removing of existing allocations which is rejected by placement and therefore
the compute service will refuse to start.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In the future when PCI tracking in Placement will be extended to device_spec
entries with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag, these entries will not allow
specifying a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; but nova will use the standard
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SRIOV_NET_VF&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VDPA_NETDEV&lt;/span&gt;&lt;/code&gt; classes. This will
not prevent type-VF and type-PF devices to be consumed via PCI alias, as the
alias can request these standard resource classes too.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The new Placement based PCI tracking feature won’t support the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; tag
in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; configuration. Usage of this tag is already limited
as not all PCI devices has a device name. Also &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; only works
properly if the names are kept stable across hypervisor reboots and upgrades.
If the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; has any entry with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; tag then the nova-compute
service will refuse to start.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="modeling-pci-devices-in-placement"&gt;
&lt;h3&gt;Modeling PCI devices in Placement&lt;/h3&gt;
&lt;p&gt;PCI device modeling in Placement will closely mirror that of vGPUs.
Each PCI device of type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PCI&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PF&lt;/span&gt;&lt;/code&gt; will be modeled as a
Placement resource provider (RP) with the name
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;hypervisor_hostname&amp;gt;_&amp;lt;pci_address&amp;gt;&lt;/span&gt;&lt;/code&gt;. The hypervisor_hostname prefix will be
the same string as the name of the root RP. The pci_address part of the
name will be the full PCI address in the same format of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DDDD:BB:AA.FF&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The pGPU RPs are using the libvirt nodedev name but this spec is not try to
follow that naming scheme as the libvirt nodedev names are not considered
stable. Also nova always uses the RP UUID to identify and RP instead of its
name. So these names are only for troubleshooting purposes.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Each PCI device RP will have an inventory of resource class and traits based
on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; entry matching with the given device. If the device
has children devices (VFs) matching with any &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry then the
resource inventory and traits of the children will be reported to the parent PF
RP too.&lt;/p&gt;
&lt;p&gt;If a PCI device is matching a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry without a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag then an inventory of 1 is reported of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; specified in the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry or if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; is not specified there then with the generated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PCI_&amp;lt;vendor_id&amp;gt;_&amp;lt;product_id&amp;gt;&lt;/span&gt;&lt;/code&gt; resource class.&lt;/p&gt;
&lt;p&gt;If a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-VF&lt;/span&gt;&lt;/code&gt; device is matching a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry then the related
resource inventory will be reported on RP representing its parent PF device.
The PF RP will be created even if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PF&lt;/span&gt;&lt;/code&gt; device is not matching any
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry but in that case, only VF inventory will exist on the RP.&lt;/p&gt;
&lt;p&gt;If multiple VFs from the same parent PF is matching the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; then
the total resource inventory of VFs will be the total number of matching VF
devices.&lt;/p&gt;
&lt;p&gt;Each PCI device RP will have traits reported according to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag
of the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry. Additionally, Nova will report the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MANAGED_PCI_DEVICE&lt;/span&gt;&lt;/code&gt; standard trait on the device RPs automatically.
This is used by the nova-compute service to reject a reconfiguration where
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is disable after it was enabled.&lt;/p&gt;
&lt;p&gt;Listing both the parent PF device and any of this children VF devices at the
same time will not be support if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is enabled. See
&lt;a class="reference internal" href="#dependent-device-handling"&gt;Dependent device handling&lt;/a&gt; section for more details.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Even though neutron-requested PCI devices are out of the scope of this spec
the handling of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PF&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-VF&lt;/span&gt;&lt;/code&gt; devices cannot be ignored as
those device types can also be requested via PCI alias by setting the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_type&lt;/span&gt;&lt;/code&gt; tag accordingly.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The PCI alias can only request devices based on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt; today and that information will be automatically included in
the Placement inventory as the resource class.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In the future Nova can be extended to automatically report PCI device
capabilities as custom traits in placement. However this is out of scope of
the current spec. If needed the deployer can add these traits via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; configuration manually.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="reporting-inventories-from-the-resourcetracker-to-placement"&gt;
&lt;h3&gt;Reporting inventories from the ResourceTracker to Placement&lt;/h3&gt;
&lt;p&gt;The ResourceTracker and the PciDevTracker implements a virt driver agnostic
PCI device inventory and allocation handling. This logic is extended to
provide PCI inventory information to Placement by translating PciDevice and
PciDeviceSpec objects to Placement resource providers, resource inventories,
and traits.&lt;/p&gt;
&lt;p&gt;This new translator logic also capable of healing missing PCI resource
allocations of existing instances based on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; field of the
allocated PciDevice objects. The missing allocations will be created in
Placement via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/reshape&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;To aid the PCI scheduling via placement this logic also records the UUID of the
resource provider representing a PCI device into the PciDevice object. Then
the existing PCI pooling logic will translate such mapping to a PCI device
pool, resource provider UUID mapping. Note that the scheduler needs one to one
mapping between resource provider and PCI device pool, so the PCI pooling logic
is changed to represent each type-PCI and PF devices as separate pools and only
pool together VFs from the same parent PF to the same Pool.&lt;/p&gt;
&lt;p&gt;The inventory and allocation handling logic will run in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource&lt;/span&gt;&lt;/code&gt; periodic as well as during resource tracked
update due to instance actions.&lt;/p&gt;
&lt;p&gt;The allocation healing part of this implementation is temporary to support
upgrading existing deployments with PCI allocations to the new Placement based
logic. As soon as a deployment is upgraded and the scheduler logic is enabled
the healing is expect to be noop as the scheduler creates all the necessary
allocation in Placement. Therefore we plan to remove the healing logic from
the codebase in a future release.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The compute restart logic needs to handle the case when a device is not
present any more either due to changes in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; config
option or due to a physical device removal from the hypervisor. The driver
needs to modify the VF resource inventory on the PF RP (when a VF is removed)
or delete the PF RP (if the PF is removed and no children VFs matched). Nova
cannot prevent the removal of a PCI device from the hypervisor while the
device is allocated to a VM. Still Nova will emit a warning in such case.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="pci-alias-configuration"&gt;
&lt;h3&gt;PCI alias configuration&lt;/h3&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#pci.alias"&gt;PCI alias definition&lt;/a&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]alias&lt;/span&gt;&lt;/code&gt; configuration option will be
extended to support two new tags, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt;. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; tag can hold exactly one resource class name. While the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag can hold a comma-separated list of trait names. Also trait names
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; can be prefixed with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;!&lt;/span&gt;&lt;/code&gt; to express a forbidden trait.
When the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; is specified, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt;
tags will no longer be required.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt; fields are
provided in the alias then Nova will use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; for the
Placement query but the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt; filtering will
happen in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Later if more complex trait requirements are needed we can add support for
multiple &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag by adding a free postfix. Also later we can add
support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in:&lt;/span&gt;&lt;/code&gt; prefix in the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag to express
an OR relationship. E.g.&lt;/p&gt;
&lt;div class="highlight-js notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"traits1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1,!T2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"traits2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in:T3,T4"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="requesting-pci-devices"&gt;
&lt;h3&gt;Requesting PCI devices&lt;/h3&gt;
&lt;p&gt;The syntax and handling of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough:alias&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/extra-specs.html#pci_passthrough:alias"&gt;flavor extra specs&lt;/a&gt;
will not change. Also, Nova will continue using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; to
track the requested PCI devices for a VM.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="scheduling"&gt;
&lt;h3&gt;Scheduling&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; creation logic is extended to translate
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; objects and store the new
groups in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt;. At this time
nova will only translate flavor based InstancePCIRequests the neutron port
based requests will be handled in a later release.&lt;/p&gt;
&lt;p&gt;This translation logic is disable by default and can be enabled via the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[filter_scheduler]pci_in_placement&lt;/span&gt;&lt;/code&gt; configuration after every compute in
the deployment is upgraded and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; configuration
option is enabled.&lt;/p&gt;
&lt;p&gt;To be able to unambiguously connect &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroups&lt;/span&gt;&lt;/code&gt; the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;request_id&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; object
always needs to be filled to a UUID. In the past nova only filled that field
for neutron based requests.&lt;/p&gt;
&lt;p&gt;A single &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; object can potentially request multiple devices
as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;count&lt;/span&gt;&lt;/code&gt; field can be set to greater than 1 for flavor based request.
In this case a single request object is split into multiple &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt;
objects to allow fulfilling those device requests from independent resource
providers. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt; of the resulting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; objects are
filled with a value generated by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest.request_id-&amp;lt;index&amp;gt;&lt;/span&gt;&lt;/code&gt;
formula where index is a runing index between 0..``count`` from the request.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required_traits&lt;/span&gt;&lt;/code&gt; filed of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; object
is filled based on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spec&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; that in
turn are filled from the fields of the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]alias&lt;/span&gt;&lt;/code&gt; entry
requested via the flavor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extras_spec&lt;/span&gt;&lt;/code&gt;. If a request comes from an alias that
does not have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; associated with it, then it will be
defaulted to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PCI_&amp;lt;vendor_id&amp;gt;_&amp;lt;product_id&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The existing scheduler implementation can be used to generate the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/allocation_candidates&lt;/span&gt;&lt;/code&gt; query to Placement including the new PCI related
groups.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependent-device-handling"&gt;
&lt;h3&gt;Dependent device handling&lt;/h3&gt;
&lt;p&gt;Today nova allows matching both a parent PF and its children VFs in the
configuration and these devices are tracked as separate resources. However,
they cannot be consumed independently. When the PF is consumed its children VFs
become unavailable. Also when a VF is consumed its parent PF becomes
unavailable. This dynamic device type selection will be deprecated and the new
Placement based PCI tracking will only allow configuring either the PF device
or its children VF devices. The old PCI tracker will continue support this
functionality but as soon as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is set to True on a
compute that compute will reject configurations that are enabling both the PF
and in children VFs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="pci-numa-affinity"&gt;
&lt;h3&gt;PCI NUMA affinity&lt;/h3&gt;
&lt;p&gt;The PCI NUMA affinity code (mostly in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hardware.py&lt;/span&gt;&lt;/code&gt;) will need to be modified
to limit the PCI devices considered to just those included in the allocation
candidate summary. Also at the same time, this code should provide information
to the scheduler about which allocation candidate is valid from affinity
perspective.&lt;/p&gt;
&lt;p&gt;To enable this the allocation candidates will be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt;
object of the filter scheduler. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; will then need to pass the allocation candidates to the
hardware.py functions which will need to remove any allocation candidates from
that list that do not fulfill the PCI or NUMA requirements. The filter should
then pop any invalid allocation candidates from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object. At
the end of the scheduling process, the filter scheduler will have to
reconstruct the host allocation candidate set from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;By extending the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object with the allocation candidate we will
enable the filters to filter not just by the host but optionally by the
allocation candidates of the host without altering the filter API therefore
maintaining compatibility with external filters.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="the-pci-stats-module"&gt;
&lt;h3&gt;The PCI stats module&lt;/h3&gt;
&lt;p&gt;The stats module will have to be enhanced to support allocation aware claims.
To the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDevicePool&lt;/span&gt;&lt;/code&gt; object needs to be mapped to resource providers. This
will be done by the PCI device inventory reporting logic in the PciDevTracker.
During a scheduling attempt the scheduler filters can provide the resource
provider UUIDs that the current allocation candidate is mapped to to restrict
the PCI fitting logic according to the candidate.&lt;/p&gt;
&lt;p&gt;After the scheduling decision is made the selected mapping is recorded into
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects. So that during the PCI claim logic this
information will be provider from those objects to ensure that the claim
consumes PCI devices that are allocated for this request in Placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vm-lifecycle-operations"&gt;
&lt;h3&gt;VM lifecycle operations&lt;/h3&gt;
&lt;p&gt;The initial scheduling is very similar to the later scheduling done due to
move operations. So, the existing implementation can be reused. Also, the
current logic that switches the source node Placement allocation to be held by
the migration UUID can be reused.&lt;/p&gt;
&lt;p&gt;Live migration is not supported with PCI alias-based PCI devices and this will
not be changed by the current spec.&lt;/p&gt;
&lt;p&gt;Attaching and detaching PCI devices are only supported via Neutron SR-IOV ports
and that is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="neutron-sr-iov-ports-out-of-scope"&gt;
&lt;h3&gt;Neutron SR-IOV ports (out of scope)&lt;/h3&gt;
&lt;p&gt;This is out of scope in the current spec. But certain aspects of the problem
are already known and therefore listed here.&lt;/p&gt;
&lt;p&gt;There are a list of Neutron port &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct-physical&lt;/span&gt;&lt;/code&gt;,etc) where the port needs to be backed by VF or PF PCI
devices.&lt;/p&gt;
&lt;p&gt;In the simpler case when a port only requires a PCI device but does
not require any other resources (e.g. bandwidth) then Nova needs to create
Placement request groups for each Neutron port with the already proposed
prefilter. See &lt;a class="reference internal" href="#scheduling"&gt;Scheduling&lt;/a&gt; for more details. In this case, neither the
name of the resource class nor the vendor ID, product ID pair is known at
scheduling time (compared to the PCI alias case) therefore the prefilter does
not know what resource class needs to be requested in the Placement request
group.&lt;/p&gt;
&lt;p&gt;To resolve this, PCI devices that are intended to be used for Neutron-based
SR-IOV should should not use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; tag in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt;. Instead Nova will use standard resource classes to
model these resource.&lt;/p&gt;
&lt;p&gt;Today nova allows consuming type-PCI or type-VF for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt; ports. This
is mostly there due to historical reasons and it should be cleaned up. A
better device categorization is suggested:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A device in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; will be consumable only via PCI alias
if it does not have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag attached.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A device that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag attached will be considered a
network device and it will be modelled as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt; resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A device that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag and also has the capability to
provide VFs will have a trait &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NIC_SRIOV&lt;/span&gt;&lt;/code&gt; but still use the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt; resource class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A device that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag and is a VF will be modelled
as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SRIOV_NET_VF&lt;/span&gt;&lt;/code&gt; resource.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way every Neutron &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; can be mapped to one single resource
class by Nova. The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; -&amp;gt; resource class mapping is
suggested:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;macvtap&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-forwarder&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote-managed&lt;/span&gt;&lt;/code&gt; -&amp;gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SRIOV_NET_VF&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct-physical&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VDPA_NETDEV&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nova will use these resource classes to report device inventories to
Placement. Then the prefilter can translate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; of the ports to
request the specific resource class during scheduling.&lt;/p&gt;
&lt;p&gt;Another specialty of Neutron-based SR-IOV is that the devices listed in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; always have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag.
This information needs to be reported as a trait to the PF RP in Placement.
Also, the port’s requested physnet needs to be included in the Placement
request group by the prefilter.&lt;/p&gt;
&lt;p&gt;There is a more complex case when the Neutron port not only requests a PCI
device but also requests additional resources (e.g. bandwidth) via the port
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; attribute. In this case, Nova already generates Placement
request groups from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; and as in the simple case will
generate a request group from the PCI request. The resource request
of these groups of a neutron port needs to be correlated to ensure that a port
gets the PCI device and the bandwidth from the same physical device. However
today the bandwidth is modeled under the Neutron RP subtree while PCI devices
will be modeled right under the root RP. So the two RPs to allocate from are
not within the same subtree. (Note that Placement always fulfills a named
request group from a single RP but allows correlating such request groups
within the same subtree.) We have multiple options here:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a scheduler filter that removes allocation candidates where these
request groups are fulfilled from different physical devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report the bandwidth and the PCI device resource on the same RP. This breaks
the clear ownership of a single RP as the bandwidth is reported by the
neutron agent while the PCI device is reported by Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move the two RPs (bandwidth and PCI dev) into the same subtree. This
needs an agreement between Nova and Neutron devs where to move the RPs and
needs an extra reshape to implement the move.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance Placement to allow sharing of resources between RPs within the same
RP tree. By that, we could make the bandwidth RP a sharing RP that shares
resources with the PCI device RP representing the physical device.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Based on the selected solution either:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Neutron requests the specific resource class for the SRIOV
port via the port &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova can include these resources to the request when the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects are created based on the requested ports.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We could keep using the legacy tracking with all its good and bad properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could track each PCI device record as a separate RP.
This would result in each VF having its own RP allowing each VF to have
different traits. This is not proposed as it will significantly increase the
possible permutations of allocation candidates per host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could keep supporting the dynamic PF or VF consumption in Placement but
it is deemed more complex than useful. We will keep supporting it via the
legacy code path but the new code path will not support it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could model each PCI device under a NUMA node.
This can be done in the future by moving the RP under a NUMA node RP instead
of the compute node RP but it is declared out of the scope of this initial
spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; object will be extended to include the required and
forbidden traits and the resource class requested via the PCI alias in the
flavor and defined in the PCI alias configuration.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDevicePool&lt;/span&gt;&lt;/code&gt; object will be extended to store a resource provider UUID so
that the PCI device allocated in Placement can be correlated to the PCI device
to be claimed by the PCI tracker.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;In general, this is expected to improve the scheduling performance but
should have no runtime performance impact on guests.&lt;/p&gt;
&lt;p&gt;The introduction of new PCI &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; objects will make the computation
of the placement query slightly longer and the resulting execution time may
increase for instances with PCI requests but should have no effect for
instances without PCI requests. This added complexity is expected to be offset
the result of the offloading of the filtering to Placement and the removal of
reschedules due to racing for the last PCI device on a host, the overall
performance is expected to improve.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;To utilize the new feature the operator will have to define two new config
options. One to enable the placement scheduling logic and a second to enable
the reporting of the PCI devices to Placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The new Placement based PCI tracking will be disabled by default. Deployments
already using PCI devices can freely upgrade to the new Nova version without
any impact. At this state the PCI device management will be done by the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; in the scheduler and the PCI claim in the PCI device
tracker in the compute service same as in the previous version of Nova.
Then after the upgrade the new PCI device tracking can be enabled in two
phases.&lt;/p&gt;
&lt;p&gt;First the PCI inventory reporting needs to be enabled by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt;&lt;/code&gt; on each compute host. During the startup of the
nova-compute service with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; config the
service will do the reshape of the provider tree and start reporting PCI device
inventory to Placement. Nova compute will also heal the PCI allocation of the
existing instances in Placement. This healing will be done for new
instances with PCI requests until a future release where the prefilter enabled
by default. This is needed to keep the resource usage in sync in Placement
even if the instance scheduling is done without the prefilter requesting
PCI allocations in Placement.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Operators are encouraged to take the opportunity to rename the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; config option to the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt;
option. The syntax of the two options are the same.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; tag is not supported in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; and in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; any more if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt;&lt;/code&gt; is
enabled. We suggest to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;address&lt;/span&gt;&lt;/code&gt; tag instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If the deployment is configured to rely on the dynamic dependent device
behavior, i.e. both the PF and its children VFs are matching the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; then reconfiguration will be needed as the new code patch
will not support this and the nova-compute service will reject to start with
such configuration. To do the reconfiguration the deployer needs to look at
the current allocation of the PCI devices on each compute node:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;if neither the PF nor any of its children VFs are allocated then the
deployer can decide which device(s) kept in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if the PF is already allocated then the PF needs to be kept in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; but all children VFs has to be removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if any of the children VF device is allocated then the parent PF needs to
be removed from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; and at least the currently allocated
VFs needs to be kept in the config, while other non allocated children VFs
can be kept or removed from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; at will.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Once &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt;&lt;/code&gt; is enabled for a compute host it cannot be
disabled any more.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Second, after every compute has been configured to report PCI inventories to
Placement the scheduling logic needs to be enabled in the nova-scheduler
configuration via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[filter_scheduler]pci_in_placement&lt;/span&gt;&lt;/code&gt; configuration
option.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;translate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt; &lt;span class="pre"&gt;objects&lt;/span&gt;&lt;/code&gt; in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;support adding resource class and required traits to PCI alias&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;split PCI pools by PCI or PF devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;map each PCI pool to the RP it represents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extend the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object with an allocations candidate list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; to filter
on allocation candidates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stats&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hardware&lt;/span&gt;&lt;/code&gt; module to consider allocation
candidates when filtering for PCI NUMA affinity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;store the allocated RP UUIDs in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extend the PCI claim code path to consume devices based on the placement
allocations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ensure that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; translation happens
before each move operation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The unified limits feature exists in an opt-in, experimental state and will
allow defining limits for the new PCI resources if enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;As this is a PCI passthrough related feature it cannot be tested in upstream
tempest. Testing will be primarily done via the extensive unit and functional
test suites that exists for instances with PCI devices and NUMA topology in the
libvirt functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The PCI passthrough doc will have to be rewritten to document the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait&lt;/span&gt;&lt;/code&gt; tags for the PCI &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; and
PCI alias.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="cpu-resource-tracking-spec"&gt;CPU resource tracking spec&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/cpu-resources.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/cpu-resources.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="unified-limits-integration-in-nova"&gt;Unified Limits Integration in Nova&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="support-virtual-gpu-resources"&gt;Support virtual GPU resources&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/add-support-for-vgpu.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/add-support-for-vgpu.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Extended and re-proposed. The inventory tracking and allocation healing
has been implemented.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 - Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish the scheduling support&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>Stable Compute UUIDs</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/implemented/stable-compute-uuid.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/stable-compute-uuid"&gt;https://blueprints.launchpad.net/nova/+spec/stable-compute-uuid&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova has long had a dependency on an unchanging hostname on the
compute nodes. This spec aims to address this limitation, at least
from the perspective of being able to detect an accidental change and
avoiding catastrophe in the database that can currently result from a
hostname change, whether intentional or not.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The nova-compute service does not have a strong correlation with the
unique identifier used to represent itself. In most cases, we use the
system hostname as the identifier by which we locate our Service and
ComputeNode records in the database. However, hostnames can change
(both intentionally and unintentionally) which makes this
problematic. The Nova project has long said “don’t do that” although
in reality, we must be less fragile and able to detect and protect
against database corruption if it happens.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want nova to be able to survive an accidental system
hostname change without damage or silent data corruption.&lt;/p&gt;
&lt;p&gt;As an operator, I want nova to detect a hostname mismatch and avoid
corrupting its database.&lt;/p&gt;
&lt;p&gt;As a deployment tool developer, I want to be able to pre-generate the
UUID for a given compute host being deployed so that I will know it
ahead of time, before starting the service.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova will use a persistent file for storing the compute node UUID for
non-Ironic environments. If this file does not exist on startup, then
it will be created once and only once. This UUID will serve to provide
a stable lookup of the ComputeNode object in the database which
represents a given nova-compute instance. This identification file
should be able to live in a non-writable (by &lt;cite&gt;nova-compute&lt;/cite&gt;) location
and treated like config, but also in a writable location and treated
like state. The latter is important to avoid adding a required
mandatory deployment step.&lt;/p&gt;
&lt;p&gt;The compute service will use this locally-persisted UUID to reliably
find the ComputeNode record, and will check for a potential hostname
(or CONF.host) change on startup. If such a rename is detected,
&lt;cite&gt;nova-compute&lt;/cite&gt; will fail to start and warn about the situation.&lt;/p&gt;
&lt;p&gt;This file will be named &lt;cite&gt;compute_id&lt;/cite&gt; and will be honored in the first
location found in any of the following locations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The parent directory of any file in &lt;cite&gt;CONF.config_files&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The directory specified in &lt;cite&gt;CONF.state_path&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For safety, all of the above locations will always be searched and any
&lt;cite&gt;compute_id&lt;/cite&gt; files found will be examined. If there are any
discrepancies (i.e. more than one files with non-identical contents),
an error will be logged and &lt;cite&gt;nova-compute&lt;/cite&gt; will refuse to start.&lt;/p&gt;
&lt;p&gt;The file format will be a single 36-character string containing a UUID
in canonical text representation (i.e. &lt;cite&gt;uuidgen &amp;gt; /path/to/file&lt;/cite&gt;).&lt;/p&gt;
&lt;p&gt;If &lt;cite&gt;nova-compute&lt;/cite&gt; is started and no &lt;cite&gt;compute_id&lt;/cite&gt; file is found, it
will be created once and initialized with a UUID in the
&lt;cite&gt;CONF.state_path&lt;/cite&gt; location.&lt;/p&gt;
&lt;p&gt;For configurations where the driver is set to Ironic, we will do no
persistence of the compute node, since there is not a 1:1 mapping
between &lt;cite&gt;nova-compute&lt;/cite&gt; instances and Ironic nodes. The mapping that
Ironic pushes up (via &lt;cite&gt;get_available_nodes()&lt;/cite&gt;) will be assumed to be
correct.&lt;/p&gt;
&lt;p&gt;Note that all drivers in Nova other than Ironic manage a single
compute node. Ironic is “special” in this regard and thus will be
special-cased for this effort.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could choose a more complex format with room for additional data or
attributes in the future. I would argue that files are cheap, easy(er)
for deployment tools to write (i.e. &lt;cite&gt;uuidgen &amp;gt; /path/to/file&lt;/cite&gt;), and
avoids the potential need for versioning and migration.&lt;/p&gt;
&lt;p&gt;We could make &lt;cite&gt;CONF.hostname&lt;/cite&gt; not optional and not defaulted to
&lt;cite&gt;socket.gethostname()&lt;/cite&gt;. This may be a simpler approach, but it is
unlikely to be favored by deployers and deployment tool writers. It
also does not provide a path to being able to actually support
hostname changes in the future.&lt;/p&gt;
&lt;p&gt;There is already some data persistence in the
&lt;cite&gt;${state_dir}/instances/compute_nodes&lt;/cite&gt; file, which is JSON-encoded and
maintained by the image cache code. I think this is a less-good idea
because it’s stored in a place that is potentially shared among
multiple (but not all) compute nodes and thus may provide a difficult
path to stable “who am I?” determination.&lt;/p&gt;
&lt;p&gt;We could use &lt;cite&gt;/etc/machine-id&lt;/cite&gt; or some amount of it. It’s not a UUID,
but it’s close. It’s also a freedesktop/systemd thing and may not
exist everywhere, especially in a containerized environment.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Right now we generate new UUIDs for records in &lt;cite&gt;compute_nodes&lt;/cite&gt; in two
ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For most drivers, it occurs rather deep in the object, in the
remotable &lt;cite&gt;create()&lt;/cite&gt; method. That means they actually get generated
on the conductor node, if the virt driver does not provide a uuid
resulting in the resource tracker calling &lt;cite&gt;create()&lt;/cite&gt; with no UUID
specified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For Ironic, the virt driver provides a uuid in the resources dict,
which causes it to be created with the desired node id from the
start.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, while not a data model impact directly, this effort will move to
always providing a &lt;cite&gt;ComputeNode.uuid&lt;/cite&gt; value when the record is
created, either because we read it from the persistent file, or
pre-generated it to write the file.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The preferred location for the &lt;cite&gt;compute_id&lt;/cite&gt; file is in one of the
config file directories, which should be non-writable by Nova
itself. If one is not provided, nova will create that file in
&lt;cite&gt;CONF.state_dir&lt;/cite&gt; which will leave it writable by the user under which
&lt;cite&gt;nova-compute&lt;/cite&gt; runs. This could potentially provide a path to
disruption, although if an attacker gains access to write things owned
by that user, all the instance disks and configs are similarly
exposed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The deployer will not be impacted by default, but will gain the
ability to pin the compute node’s UUID as config, if desired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For the 2023.1 cycle, nova-compute will need to gracefully handle the
case where there &lt;em&gt;is&lt;/em&gt; a &lt;cite&gt;ComputeNode&lt;/cite&gt; that represents its service,
which has not yet been persisted to the &lt;cite&gt;compute_id&lt;/cite&gt; file. We will
need to communicate this in the release notes, warning of the danger
of getting it wrong (which is pretty much the same as a rename
today). For the period in which we support this compatibility
behavior, we can use the &lt;cite&gt;Service.version&lt;/cite&gt; that we find attached to
our &lt;cite&gt;ComputeNode&lt;/cite&gt; object to determine whether or not we should write
an existing UUID to the &lt;cite&gt;compute_id&lt;/cite&gt; file or generate it from
scratch. In a subsequent release we should remove that behavior
(although potentially retain a start-blocking check if the version is
being upgraded across that boundary).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Write and test routines for reading, writing, and sanity-checking
the &lt;cite&gt;compute_id&lt;/cite&gt; files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the &lt;cite&gt;init_host()&lt;/cite&gt; logic to ensure the compatibility behavior
of writing existing compute node UUIDs to the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the existing compute node creation logic to honor/generate
the persistent &lt;cite&gt;compute_id&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional testing will be sufficient coverage for
this. We will get grenade and greenfield devstack coverage by default,
and perhaps we can ensure that the file is created in job post scripts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The installation guide will need changes to describe the purpose and
behavior of this file. Obviously release notes will be needed for
signaling.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This is part of a larger multi-cycle effort to
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/backlog/robustify-compute-hostnames.html"&gt;robustify compute hostnames&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 08 Mar 2023 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result operators need to ensure that Manila
backend storage is routable from the guest subnets.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not
be covered by this spec, any requests to shelve, evacuate, resize, cold migrate
or live migrate an instance with a share attached will be rejected with a
HTTP409 response for the time being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
once &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;support lands in libvirt itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.
(ref: &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user documentation&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Two new compute capability traits and filters will be introduced to model an
individual compute’s support for virtio-fs and file backed memory.
And while associating a share to an instance, a check will ensure the host
running the instance will support the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and either the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;that the instance is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;From an operator’s point of view, it means
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; support requires that
operators must upgrade all their compute nodes to the version supporting
shares using virtiofs.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; support requires that operators configure one or
more hosts with file backed memory. Ensuring the instance will land on one of
these hosts can be achieved by creating an AZ englobing these hosts.
And then instruct users to deploy their instances in this AZ.
Alternatively, operators can guide the scheduler to choose a suitable host
by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_MEM_BACKING_FILE=required&lt;/span&gt;&lt;/code&gt; as an extra spec or
image property.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the users with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;p&gt;Share mapping status:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                     &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;   &lt;span class="n"&gt;Reboot&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
    &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;--------------+&lt;/span&gt;
    &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;mounted&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;active&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;umount&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;error&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+-------------+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="n"&gt;φ&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Attach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;unmounted&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="n"&gt;v&lt;/span&gt;                                 &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+--------------&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;inactive&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;φ&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means no entry in the database. No association between a share and a server.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Attach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means POST /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Detach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means DELETE /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This chart describe the share mapping status (nova), this is independent from
the status of the Manila share.&lt;/p&gt;
&lt;p&gt;Share attachment/detachment can only be done if the VM state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;.
These are operations only on the database, and no RPC calls will be required
to the compute API. This is an intentional design for this spec.
As a result, this could lead to situation where the VM start operation fails
as an underlying share attach fails.&lt;/p&gt;
&lt;p&gt;Mount operation will be done when the share is not mounted on the compute host.
If a previous share would have been mounted on the compute host for another
server, then it will attempt to mount it and a warning will be logged that
the share was already mounted.&lt;/p&gt;
&lt;p&gt;Umount operation will be really done when the share is mounted and not used
anymore by another server.&lt;/p&gt;
&lt;p&gt;With the above mount and umount operation, the state is stored in memory and
do not require a lookup in the database.&lt;/p&gt;
&lt;p&gt;The share will be mounted on the compute host using read/write mode.
Read-only will not be supported as a share could not be mounted read-only
and read/write at the same time. If the user wants to mount the share
read-only, it will have to do it in the VM fstab.&lt;/p&gt;
&lt;p&gt;Manila share removal issue:&lt;/p&gt;
&lt;p&gt;Despite a share being used by instances, it can be removed by the user.
As a result, the instances will lose access to the data and might cause
difficulties in removing the missing share and fixing the instance.
This is an identified issue that requires Manila modifications.
A solution was identified with the Manila team to attach metadata to the share
access-allow policy that will lock the share and prevent its deletion until
the lock is not removed.
If the above Manila change can land in the Zed cycle,
the proposal here is to use the lock mechanism in Nova.
Otherwise, clearly document the known issue as unsupported and warn users that
they should take care and avoid this pitfall.&lt;/p&gt;
&lt;p&gt;Instance metadata:&lt;/p&gt;
&lt;p&gt;Add instace shares in the instance metadata.
Extend DeviceMetadata with ShareMetadata object containing &lt;cite&gt;shareId&lt;/cite&gt; and
&lt;cite&gt;tag&lt;/cite&gt; used to mount the virtiofs on an instance by the user.
See &lt;a class="reference internal" href="#bobcat-other-end-user-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PROJECT_ADMIN will be able to see details of the attachment id and export
location stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance should have the required capabilities to enable
virtiofs (see above).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a synchronous API. As a result, the VM share attachement state
is defined in the database and set as inactive.
Then, power on the VM will do the required operations to attach the share and
set it as active if there are no errors.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter in the request body, when not
provided it will be the shareId(UUID) as always provided in the request.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; if povided by the user must be an ASCII string with a maximum
lenght of 64 bytes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Primary key autoincrement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inactive&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within
the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the
underlying host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_proto&lt;/span&gt;&lt;/code&gt; - The Shared File Systems protocol (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NFS&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CEPHFS&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;The database field &lt;cite&gt;status&lt;/cite&gt; and &lt;cite&gt;share_proto&lt;/cite&gt; values will not be enforced
using enums allowing future changes and avoid database migrations.
However, to make code more robust, enums will be defined on the object fields.&lt;/p&gt;
&lt;p&gt;Fields containing text will use String and not Text type in the database schema
to limit the column width and be stored inline in the database.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to mount the
share to the host and the host filesystem location should
not be logged by Nova and only accessible by default through the API by admins.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One to add new notifications for share attach and share detach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One to extend the instance update notification with the share mapping
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Share mapping in the instance payload will be optional and controlled via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include_share_mapping&lt;/span&gt;&lt;/code&gt; notification configuration parameter. It will be
disabled by default.&lt;/p&gt;
&lt;p&gt;Proposed payload for attached and detached notification will be the same as
the one returned by the show command with admin rights.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Proposed instance payload for instance updade, will be the list of share
attached to this instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-ffffffffffff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7987"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server2.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="bobcat-other-end-user-impact"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Users could use the instance metadata to discover and auto mount the share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.
While there will be near local performance between the vm and host,
the actual performance will be limited by the network performance of
the network file share protocol and hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and capability traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (initial contributor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new capability traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 07 Mar 2023 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sun, 29 Jan 2023 00:00:00 </pubDate></item><item><title>Add maxphysaddr support for Libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/libvirt-maxphysaddr-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-maxphysaddr-support"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-maxphysaddr-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint propose new flavor extra_specs to control the physical
address bits of vCPUs in Libvirt guests.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When booting a guest with 1TB+ RAM, the default physical address bits are
too small and the boot fails &lt;a class="footnote-reference brackets" href="#id9" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. So a knob is needed to specify the
appropriate physical address bits.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Booting a guest with large RAM.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In Libvirt v8.7.0+ and QEMU v2.7.0+, physical address bits can be specified
with following XML elements &lt;a class="footnote-reference brackets" href="#id10" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id11" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. The former means to adopt any physical
address bits, the latter means to adopt the physical address bits of the
host CPU.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;maxphysaddr&lt;/span&gt; &lt;span class="pre"&gt;mode='emulate'&lt;/span&gt; &lt;span class="pre"&gt;bits='42'/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;maxphysaddr&lt;/span&gt; &lt;span class="pre"&gt;mode='passthrough'/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="flavor-extra-specs"&gt;
&lt;h3&gt;Flavor extra_specs&lt;/h3&gt;
&lt;p&gt;Here I suggest the following two flavor extra_specs.
Of course, if these are omitted, the behavior is the same as before.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode&lt;/span&gt;&lt;/code&gt; can be either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;emulate&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passthrough&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt; takes a positive integer value.
Only meaningful and must be specified if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="nova-scheduler-changes"&gt;
&lt;h3&gt;Nova scheduler changes&lt;/h3&gt;
&lt;p&gt;Nova scheduler also needs to be modified to take these two properties
into account.&lt;/p&gt;
&lt;p&gt;There can be a mix of supported and unsupported hosts depending
on Libvirt and QEMU versions. So add new traits
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_PASSTHROUGH&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt;
to check the scheduled host supports this feature.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_ADDRESS_SPACE_PASSTHROUGH=required&lt;/span&gt;&lt;/code&gt; is automatically added
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; is specified in flavor extra_specs.
And same for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Passthrough and emulate modes have different properties. So let’s consider
the two separately.&lt;/p&gt;
&lt;p&gt;The case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt;. In this case,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt; is a requirement, which is already taken
into account in nova scheduling, and no additional modifications are
required in this proposal. It is not guaranteed whether the instance
can be migrated by nova. So the admin needs to make sure that targets
of cold and live migration have similar hardware and software.
This restriction is similar for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. In nova scheduling,
it is necessary to check that the hypervisor supports at least
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_bits&lt;/span&gt;&lt;/code&gt;. The maximum number of bits supported by
hypervisor can be obtained by using libvirt capabilities &lt;a class="footnote-reference brackets" href="#id12" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Therefore,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; can be used to compare the number of bits in
scheduling.  For example, this can be accomplished by adding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;capabilities:cpu_info:maxphysaddr:bits&amp;gt;=42&lt;/span&gt;&lt;/code&gt; automatically.
Cold migration and live migration can also be realized with this filter
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt; trait.
So the overall flavor extra_specs look like the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maxphysaddr_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;emulate&lt;/span&gt; \
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maxphysaddr_bits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since ComputeCapabilitiesFilter only supports flavor extra_specs
and not image properties &lt;a class="footnote-reference brackets" href="#id13" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, this proposal is out of scope for
image properties.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Before the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxphysaddr&lt;/span&gt;&lt;/code&gt; option was introduced into Libvirt, it was specified
as a workaround with the QEMU comanndline parameter. But this alternative is
not allowed in nova.&lt;/p&gt;
&lt;p&gt;Also, some Linux distributions may have machine types with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host-phys-bits=true&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id14" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. For example, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc-i440fx-bionic-hpb&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc-q35-bionic-hpb&lt;/span&gt;&lt;/code&gt;. However, this alternative has following two issues and
cannot be adopted for general-purpose use cases.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ubuntu package maintainers are applying a patch to QEMU &lt;a class="footnote-reference brackets" href="#id15" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. It means this
is not included in vanilla QEMU and is not available in other distributions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is only the case for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; and does not
include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=emulate&lt;/span&gt;&lt;/code&gt;. Since
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:maxphysaddr_mode=passthrough&lt;/span&gt;&lt;/code&gt; requires &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-passthrough&lt;/span&gt;&lt;/code&gt;
to be used &lt;a class="footnote-reference brackets" href="#id16" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, this alternative cannot be used with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=custom&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode=host-model&lt;/span&gt;&lt;/code&gt;. So, this alternative is not sufficient for
a cloud with many different CPU models.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As for scheduling, placement does not currently support numeric traits,
so the maximum number of bits supported by hypervisor cannot be checked
by this mechanism.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators should specify appropriate flavor extra_specs as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As described earlier, the new traits &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_PASSTHROUGH&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_ADDRESS_SPACE_EMULATED&lt;/span&gt;&lt;/code&gt; signal if the upgraded compute nodes support
this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nmiki&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new guest configs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fileds in nova/api/validation/extra_specs/hw.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new fields in LibvirtConfigCPU in nova/virt/livbirt/config.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new traits to check Libvirt and QEMU versions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxphysaddr&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info&lt;/span&gt;&lt;/code&gt; in nova/virt/libvirt/driver.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs and release notes for new flavor extra_specs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Libivrt v8.7.0+.
QEMU v2.7.0+.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add the following unit tests:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;check that proposed flavor extra_specs are properly validated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that intended XML elements are output&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that traits are properly added and used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check that new field in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeCapabilitiesFilter&lt;/span&gt;&lt;/code&gt; is property
added and used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;For operators, the documentation describes what proposed flavor extra_specs
mean and how they should be set.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1769053"&gt;https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1769053&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/news.html#v8-7-0-2022-09-01"&gt;https://libvirt.org/news.html#v8-7-0-2022-09-01&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/commit/1c1a7cdd4096c59fb0c374529e1e5aea8d43ee9c"&gt;https://github.com/libvirt/libvirt/commit/1c1a7cdd4096c59fb0c374529e1e5aea8d43ee9c&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatcaps.html#examples"&gt;https://libvirt.org/formatcaps.html#examples&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/scheduling.html#computecapabilitiesfilter"&gt;https://docs.openstack.org/nova/latest/admin/scheduling.html#computecapabilitiesfilter&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id14" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://cpaelzer.github.io/blogs/005-guests-bigger-than-1tb/"&gt;https://cpaelzer.github.io/blogs/005-guests-bigger-than-1tb/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/commit/?id=6ba8b5c843d405e1b067dc8b98ecb8545af78a2b"&gt;https://git.launchpad.net/~paelzer/ubuntu/+source/qemu/commit/?id=6ba8b5c843d405e1b067dc8b98ecb8545af78a2b&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/blob/v8.7.0/src/qemu/qemu_validate.c#L346-L351"&gt;https://github.com/libvirt/libvirt/blob/v8.7.0/src/qemu/qemu_validate.c#L346-L351&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id17"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 15 Dec 2022 00:00:00 </pubDate></item><item><title>Review usage of oslo-privsep library on Nova</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/privsep-usage-review.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/privsep-usage-review"&gt;https://blueprints.launchpad.net/nova/+spec/privsep-usage-review&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova’s usage of the privsep library is too broad. A single global permission
profile with all needed capabilities is defined for all functions that interact
with privsep to use. While this works, it is not the best usage of the library
as functions are getting a set of rights they do not need and thus should not
receive. This spec seeks to fix this situation by defining a more specialized
usage of the library.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova compute services use the oslo-privsep library to obtain elevated
privileges on the host system with the intention of invoking python functions
or linux commands that affect areas of the host that require of such
privileges.&lt;/p&gt;
&lt;p&gt;Today, Nova’s usage of privsep follows best practices that were recommended
by the library when it was first created:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create a dedicated module for privileged functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a single context and restrict its usage to that module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limit scope of privileged functions and reuse their actions as unprivileged
code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on usage of the library over the years, it has become clear that this
approach is neither secure nor desirable to be continued. In the current
design, a single profile is shared by all functions that make use of the
library. This one aggregates all capabilities required by all privileged
functions on the code. This means that for a single function that operates
over the filesystem, all the other ones that do not also get such capability.
This fact may lead to unexpected behaviors that can be avoided if more precise
profiles are used for each case.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a developer, I want to have a fined tuned method for acquiring capabilities.
As an admin, I want Nova to use as little elevated privileges as possible.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Given that all current functions that use the privsep library are found under
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.privsep&lt;/span&gt;&lt;/code&gt;. First step is to study and map each with the capabilities
they require. Next, a set of profiles can be defined for common use cases,
such as network or system rights, and cover with them as much as possible.
The rest will have to be divided into smaller functions that do fit into one
of those profiles. If that is not possible, then the current all-capable
profile will need to be kept for them until a better solution is found.&lt;/p&gt;
&lt;p&gt;Profiles will now be defined under the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__init__.py&lt;/span&gt;&lt;/code&gt; file found at:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/master/nova/__init__.py"&gt;https://github.com/openstack/nova/blob/master/nova/__init__.py&lt;/a&gt;, while
functions using these will be distributed through other packages. Here is an
example on how the file may end up looking like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;legacy_pctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priv_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'nova'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cfg_section&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'nova_sys_admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pypath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'.legacy_pctxt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_CHOWN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_DAC_OVERRIDE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_DAC_READ_SEARCH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_FOWNER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_NET_ADMIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_SYS_ADMIN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;sys_admin_pctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priv_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'nova'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cfg_section&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'privsep_sys_admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pypath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'.sys_admin_pctxt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_SYS_ADMIN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;net_admin_pctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priv_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'nova'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cfg_section&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'privsep_net_admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pypath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'.net_admin_pctxt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_NET_ADMIN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;file_admin_pctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priv_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'nova'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cfg_section&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'privsep_file_admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pypath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'.file_admin_pctxt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_CHOWN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_DAC_OVERRIDE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_DAC_READ_SEARCH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_FOWNER&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Each newly defined profile will spawn a daemon that consumes resources on the
host. For such reason, no more than 4 profiles may be defined at a single time
to avoid over encumbering it.&lt;/p&gt;
&lt;p&gt;For the sake of improving usability, shared code found across the package’s
functions should be extracted into other, unprivileged functions with broader
contracts. These will take care of performing more generic actions, like
‘chown’ or ‘mkdir’, that may not require more than the user’s rights to be
done. When elevated permissions are required though, specialized single use
functions with a narrow contract will be defined using one of the new privsep
contexts. These functions will be created following these conditions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Will contain the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;privileged_&lt;/span&gt;&lt;/code&gt; prefix on their name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will be defined at the same package that uses them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will only be imported by a single module, excepting unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is an example of how this implementation would be like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# in nova/common/filesytem.py&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;write_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;chown_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;

&lt;span class="c1"&gt;# in nova/virt/libvirt/driver.py&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;nova&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;nova.common&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;filesystem&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="nd"&gt;@nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_admin_pctxt&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;privileged_write_tpm_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;tpm_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;oslo_utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuidutils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_uuid_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"instance: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is not a valid uuid"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instace_state_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tpm_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'wb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chown_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"nova"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"qemu"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None that I can think of. Please, provide any feedback on the scope of this
spec and its approach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Requires the use of elevated privileges.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In case the tenant’s openstack distribution does not use defaults for
elevated privileges configuration, then the privsep daemons spawned after this
spec must be configured following the options at:
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#privsep"&gt;https://docs.openstack.org/nova/latest/configuration/config.html#privsep&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers will need to analyze which capabilities are required for any new
functions under &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.privsep&lt;/span&gt;&lt;/code&gt; and apply the correct profile accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jsanemet&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sylvainb&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Study functions that already use oslo-privsep to determine which capabilities
each need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define profiles for functions that share a common context, i.e.: run a system
command, modify network settings…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Tempest tests must continue to pass without the need for any modifications,
verifying that everything still works the same running under reduced
permission sets.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;First discussed at:
&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-privsep-review"&gt;https://etherpad.opendev.org/p/nova-privsep-review&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 23 Nov 2022 00:00:00 </pubDate></item><item><title>Policy Service Role Default</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/policy-service-role-default.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/policy-service-role-default"&gt;https://blueprints.launchpad.net/nova/+spec/policy-service-role-default&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally all internal service-to-service APIs should not be accessible
by admin or end user by default. From policy defaults it should be
clear which APIs are supposed to be used by admin or end user and
which is for internal service-to-service APIs communication.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, internal service-to-service communication APIs have their
default policy as either admin or project roles which means operators
need to assign the admin or project roles to their service users.
That service user having admin or project role access is poor security
practice as they can perform admin or project level operations.&lt;/p&gt;
&lt;p&gt;Another problem is that APIs which are meant to only be used by internal
services are able to be called by regular users and human admins. Requiring
(and allowing only) a service role for these APIs help avoid intentional
and accidental abuse.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I want to keep &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user to access
service-to-service APIs with least privilege.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We need to make sure all the policy rules for internal service-to-service
APIs are default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role only. Example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:os-server-external-events:create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'role:service'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'project'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Keystone’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role is kept outside of the existing role hierarchy
that includes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader&lt;/span&gt;&lt;/code&gt;. Keeping the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
role outside the current hierarchy ensures we’re following the principle
of least privilege for service accounts.&lt;/p&gt;
&lt;p&gt;We need to make all the service-to-service APIs which are &lt;em&gt;only&lt;/em&gt; suitable
for services default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role only. But we might have some cases
where APIs are both intended for service usage, as well as admin (any other
user role) usage. For such policy rules we need to default them to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
as well as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; (or any other user role) role. For example,
‘role:admin or role:service’&lt;/p&gt;
&lt;p&gt;As Nova have dropped the system scope implementation, service-to-service
communication with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role will be done with project scope token
(which is currently done in devstack setup).&lt;/p&gt;
&lt;p&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:delete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-volumes-attachments:swap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-server-external-events:create&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep the service-to-service APIs default same as it is and expect operators
to take care of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role users access permissions by overriding
it in the policy.yaml.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Below APIs policy will be default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-assisted-volume-snapshots:delete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-volumes-attachments:swap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_compute_api:os-server-external-events:create&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Easier to understand service-to-service APIs policy and restricting them to
least privilege.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If service-to-service APIs are used by the admin or end user then make
sure to override the required permission in policy.yaml because by default
they will be accessed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New APIs must add policies that follow the new pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;If service-to-service APIs are used by the admin or end user then make
sure to override the required permission in policy.yaml because by default
they will be accessed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role user only. If deployment
overrides these policies then, they need to start considering the new
default policy rules.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Modify the service-to-service APIs defaults&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify policy rule unit tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Modify or add the policy unit tests.&lt;/p&gt;
&lt;p&gt;Add a job enabling the new defaults and run the tempest tests to make sure
existing service-service APIs communication work fine. If needed modify the
token used by services as per the new defaults.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;API Reference should be updated to add all the service-service APIs under
separate section and mention about &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role as their default.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 Nov 2022 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result operators need to ensure that Manila
backend storage is routable from the guest subnets.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not
be covered by this spec, any requests to shelve, evacuate, resize, cold migrate
or live migrate an instance with a share attached will be rejected with a
HTTP409 response for the time being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
once &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;support lands in libvirt itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.
(ref: &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user documentation&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Two new compute capability traits and filters will be introduced to model an
individual compute’s support for virtio-fs and file backed memory.
And while associating a share to an instance, a check will ensure the host
running the instance will support the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and either the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;that the instance is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;From an operator’s point of view, it means
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; support requires that
operators must upgrade all their compute nodes to the version supporting
shares using virtiofs.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; support requires that operators configure one or
more hosts with file backed memory. Ensuring the instance will land on one of
these hosts can be achieved by creating an AZ englobing these hosts.
And then instruct users to deploy their instances in this AZ.
Alternatively, operators can guide the scheduler to choose a suitable host
by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_MEM_BACKING_FILE=required&lt;/span&gt;&lt;/code&gt; as an extra spec or
image property.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the users with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;p&gt;Share mapping status:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                     &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;   &lt;span class="n"&gt;Reboot&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
    &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;--------------+&lt;/span&gt;
    &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;mounted&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;active&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;umount&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;error&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+-------------+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="n"&gt;φ&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Attach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;unmounted&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="n"&gt;v&lt;/span&gt;                                 &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+--------------&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;inactive&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;φ&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means no entry in the database. No association between a share and a server.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Attach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means POST /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Detach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means DELETE /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This chart describe the share mapping status (nova), this is independent from
the status of the Manila share.&lt;/p&gt;
&lt;p&gt;Share attachment/detachment can only be done if the VM state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;.
These are operations only on the database, and no RPC calls will be required
to the compute API. This is an intentional design for this spec.
As a result, this could lead to situation where the VM start operation fails
as an underlying share attach fails.&lt;/p&gt;
&lt;p&gt;Mount operation will be done when the share is not mounted on the compute host.
If a previous share would have been mounted on the compute host for another
server, then it will attempt to mount it and a warning will be logged that
the share was already mounted.&lt;/p&gt;
&lt;p&gt;Umount operation will be really done when the share is mounted and not used
anymore by another server.&lt;/p&gt;
&lt;p&gt;With the above mount and umount operation, the state is stored in memory and
do not require a lookup in the database.&lt;/p&gt;
&lt;p&gt;The share will be mounted on the compute host using read/write mode.
Read-only will not be supported as a share could not be mounted read-only
and read/write at the same time. If the user wants to mount the share
read-only, it will have to do it in the VM fstab.&lt;/p&gt;
&lt;p&gt;Manila share removal issue:&lt;/p&gt;
&lt;p&gt;Despite a share being used by instances, it can be removed by the user.
As a result, the instances will lose access to the data and might cause
difficulties in removing the missing share and fixing the instance.
This is an identified issue that requires Manila modifications.
A solution was identified with the Manila team to attach metadata to the share
access-allow policy that will lock the share and prevent its deletion until
the lock is not removed.
If the above Manila change can land in the Zed cycle,
the proposal here is to use the lock mechanism in Nova.
Otherwise, clearly document the known issue as unsupported and warn users that
they should take care and avoid this pitfall.&lt;/p&gt;
&lt;p&gt;Instance metadata:&lt;/p&gt;
&lt;p&gt;Add instace shares in the instance metadata.
Extend DeviceMetadata with ShareMetadata object containing &lt;cite&gt;shareId&lt;/cite&gt; and
&lt;cite&gt;tag&lt;/cite&gt; used to mount the virtiofs on an instance by the user.
See &lt;a class="reference internal" href="#antelope-other-end-user-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PROJECT_ADMIN will be able to see details of the attachment id and export
location stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance should have the required capabilities to enable
virtiofs (see above).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a synchronous API. As a result, the VM share attachement state
is defined in the database and set as inactive.
Then, power on the VM will do the required operations to attach the share and
set it as active if there are no errors.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter in the request body, when not
provided it will be the shareId(UUID) as always provided in the request.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; if povided by the user must be an ASCII string with a maximum
lenght of 64 bytes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Primary key autoincrement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inactive&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within
the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the
underlying host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_proto&lt;/span&gt;&lt;/code&gt; - The Shared File Systems protocol (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NFS&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CEPHFS&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;The database field &lt;cite&gt;status&lt;/cite&gt; and &lt;cite&gt;share_proto&lt;/cite&gt; values will not be enforced
using enums allowing future changes and avoid database migrations.
However, to make code more robust, enums will be defined on the object fields.&lt;/p&gt;
&lt;p&gt;Fields containing text will use String and not Text type in the database schema
to limit the column width and be stored inline in the database.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to mount the
share to the host and the host filesystem location should
not be logged by Nova and only accessible by default through the API by admins.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One to add new notifications for share attach and share detach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One to extend the instance update notification with the share mapping
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Share mapping in the instance payload will be optional and controlled via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include_share_mapping&lt;/span&gt;&lt;/code&gt; notification configuration parameter. It will be
disabled by default.&lt;/p&gt;
&lt;p&gt;Proposed payload for attached and detached notification will be the same as
the one returned by the show command with admin rights.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Proposed instance payload for instance updade, will be the list of share
attached to this instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-ffffffffffff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7987"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server2.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="antelope-other-end-user-impact"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Users could use the instance metadata to discover and auto mount the share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.
While there will be near local performance between the vm and host,
the actual performance will be limited by the network performance of
the network file share protocol and hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and capability traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (initial contributor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new capability traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 10 Nov 2022 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store a symmetric key in the key manager. This
remains a long running piece of technical debt in the encrypted volume
implementation as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; does not directly encrypt data with the provided
key.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID.&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypt these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; imagebackend, both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]images_type&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt;
&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]use_cow_images&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; must be configured in order for
resize to work. This is also true without encryption but it may still be
helpful to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that a user must have policy permission to create secrets in
Barbican in order for encryption to work for that user. Secrets are created
in Barbican using the user’s auth token. Admins have permission to create
secrets in Barbican by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/ephemeral-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/ephemeral-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 09 Nov 2022 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will only cover the high level changes to the API and compute
layers, implementation within specific virt drivers is left for separate
specs.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; field will be unused and not exposed to end
users initially because of the security and upgrade implications around it.
For the first pass, sensible defaults for the cipher algorithm, cipher
mode, and initialization vector generator algorithm will be hard-coded
instead.&lt;/p&gt;
&lt;p&gt;Encryption options could be exposed to end users in the future when a
proper design which addresses security and handles all upgrade scenarios is
developed.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility trait was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 09 Nov 2022 00:00:00 </pubDate></item><item><title>Per Process Healthcheck endpoints</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/per-process-healthchecks.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks"&gt;https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In many modern deployment frameworks, there is an expectation that
an application can expose a health-check endpoint so that the binary
status can be monitored. Nova currently does not provide a native way
to inspect the health of its binaries which doesn’t help cloud monitoring
and maintenance. While limited support exists for health checks via
Oslo middleware for our WSGI based API binaries, this blueprint seeks
to expose a local HTTP health-check endpoint to address this
feature gap consistently for all Nova components.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;To monitor the health of a Nova service today requires experience to
develop and implement a series of external heuristics to infer the state
of the service binaries.&lt;/p&gt;
&lt;p&gt;This can be as simple as checking the service status for those with heartbeats
or can comprise monitoring log output via a watchdog and restarting
the service if no output is detected after a protracted period.
Processing the logs for known error messages and executing a remediation script
or other methods that are easy to do incorrectly are also common.&lt;/p&gt;
&lt;p&gt;This is also quite unfriendly to new Nova users who have not gained enough
experience with operating Nova to know what warning signs they should look
for such as inability to connect to the message bus. Nova developers however
do know what some of the important health indicators are and can expose
those as a local health-check endpoint that operators can use instead.&lt;/p&gt;
&lt;p&gt;The existing Oslo middleware does not address this problem statement because:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;It can only be used by the API and metadata binaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The middleware does not tell you the service is alive if its hosted by a
WSGI server like Apache since the middleware is executed independently from
the WSGI application. i.e. the middleware can pass while the nova-api can’t
connect to the DB and is otherwise broken.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Oslo middleware in detailed mode leaks info about the host Python
kernel, Python version and hostname which can be used to determine in the
host is vulnerable to CVEs which means it should never be exposed to the
Internet. e.g.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Linux-5.15.2-xanmod1-tt-x86_64-with-glibc2.2.5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;python_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3.8.12 (default, Aug 30 2021, 16:42:10) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[GCC 10.3.0]'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want a simple REST endpoint I can consume to know
if a Nova process is healthy.&lt;/p&gt;
&lt;p&gt;As an operator I want this health check to not impact the performance of the
service so it can be queried frequently at short intervals.&lt;/p&gt;
&lt;p&gt;As a deployment tool implementer, I want the health check to be local with no
dependencies on other hosts or services to function so I can integrate it with
service managers such as systemd or a container runtime like Docker.&lt;/p&gt;
&lt;p&gt;As a packager, I would like the use of the health check endpoints to not
require special clients or packages to consume them. cURL, socat, or netcat
should be all that is required to connect to the health check and retrieve the
service status.&lt;/p&gt;
&lt;p&gt;As an operator I would like to be able to use health-check of the Nova API and
metadata services to manage the membership of endpoints in my load-balancer
or reverse proxy automatically.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="definitions"&gt;
&lt;h3&gt;Definitions&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TTL&lt;/span&gt;&lt;/code&gt;: The time interval for which a health check item is valid.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;: all health indicators are passing and their TTLs have not expired.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;: any health indicator has an expired TTL or where there is
a partial transient failure.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;: any health indicator is reporting an error or all TTLs are expired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="warn-vs-fail"&gt;
&lt;h3&gt;Warn vs fail&lt;/h3&gt;
&lt;p&gt;In general if any of the health check indicators are failing then the service
should be reported as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; however if the specific error condition is
recoverable or only a partial failure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state can and should be
used.&lt;/p&gt;
&lt;p&gt;An example of this is a service that has lost a connection to the message bus.
When the connection is lost it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state, if the first
attempt to reconnect fails it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state. Transient
failure should be considered warning but persistent errors should be escalated
to failures.&lt;/p&gt;
&lt;p&gt;In many cases external management systems will treat &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; as
equivalent and raise an alarm or restart the service. While this spec does
not specify how you should recover from a degraded state, it is
important to include a human readable description of why the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state was entered.&lt;/p&gt;
&lt;p&gt;Services in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state are still considered healthy in most cases but
they may be about to fail soon or be partially degraded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;Code changes&lt;/h3&gt;
&lt;p&gt;A new top-level Nova health check module will be created to encapsulate the
common code and data structure required to implement this feature.&lt;/p&gt;
&lt;p&gt;A new health check manager class will be introduced which will maintain the
health-check state and all functions related to retrieving, updating and
summarizing that state.&lt;/p&gt;
&lt;p&gt;The health check manager will be responsible for creating the health check
endpoint when it is enabled in the nova.conf and exposing the health check
over HTTP.&lt;/p&gt;
&lt;p&gt;The initial implementation will support HTTP over TCP with optional support for
UNIX domain sockets as a more secure alternative to be added later.
The HTTP endpoint in both cases will be unauthenticated and the response will
be in JSON format.&lt;/p&gt;
&lt;p&gt;A new HealthcheckStausItem data class will be introduced to store an
individual health check data-point. The HealtcheckStatusItem will contain
the name of the health check, its status, the time it was recorded,
and an optional output string that should be populated if the
status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A new decorator will be introduced that will automatically retrieve the
reference to the healthcheck manager from the Nova context object and update
the result based on whether the function decorated raises an exception or not.
The exception list and healthcheck item name will be specifiable.&lt;/p&gt;
&lt;p&gt;The decorator will accept the name of the health check as a positional argument
and include the exception message as the output of the health check on failure.
Note that the decorator will only support the pass or fail status for
simplicity; where warn is appropriate a manual check should be written.
If multiple functions act as indicators of the same capability the same name
should be used.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_other_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default all exceptions will be caught and re-raised by the decorator.&lt;/p&gt;
&lt;p&gt;The new REST health check endpoint exposed by this spec will initially only
support one URL path &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt;. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; endpoint will include a
&lt;cite&gt;Cache-Control: max-age=&amp;lt;ttl&amp;gt;&lt;/cite&gt; header as part of its response which can
optionally be consumed by the client.&lt;/p&gt;
&lt;p&gt;The endpoint may also implement a simple incrementing etag at a later date
once the initial implementation is complete, if required.
Initially adding an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; is not provided as the response is expected to be
small and cheap to query, so etags do not actually provide much benefit form
a performance perspective.&lt;/p&gt;
&lt;p&gt;If implemented, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; will be incremented whenever the service state
changes and will reset to 0 when the service is restarted.&lt;/p&gt;
&lt;p&gt;Additional URL paths may be supported in the future, for example to retrieve
the running configuration or trigger the generation of Guru Meditation Reports
or enable debug logging. However, any endpoint beyond &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; is out of
scope of this spec. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; is not used for health check response to facilitate
additional paths in the future.&lt;/p&gt;
&lt;section id="example-output"&gt;
&lt;h4&gt;Example output&lt;/h4&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"e3c22423-cd7a-47dc-b6e9-e18d1a8b3bdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"api_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="n"&gt;Sevice&lt;/span&gt; &lt;span class="n"&gt;Unavailable&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0a47dceb-11b1-4d94-8b9c-927d998be320"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-compute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"controller-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"hypervisor"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
             &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:05:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s2"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Libvirt Error: ..."&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of maintaining the state of the process in a data structure and
returning the cached state we, could implement the health check as a series of
active probes such as checking the DB schema version to ensure we can access
it or making a ping RPC call to the cell conductor or our own services RPC
endpoint.&lt;/p&gt;
&lt;p&gt;While this approach has some advantages it will have a negative performance
impact if the health-check is queried frequently or in a large deployment where
infrequent queries may still degrade the DB and message bus performance due to
the scale of the deployment.&lt;/p&gt;
&lt;p&gt;This spec initially suggested using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OK&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Degraded&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Faulty&lt;/span&gt;&lt;/code&gt; as the
values for the status field. These were updated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; to align with the draft IETF RFC for health check response format for
HTTP APIs &lt;a class="reference external" href="https://tools.ietf.org/id/draft-inadarei-api-health-check-06.html"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The Nova context object will be extended to store a reference to the
health check manager.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While this change will expose a new REST API endpoint it will not be
part of the existing Nova API.&lt;/p&gt;
&lt;p&gt;In the Nova API the /health check route will not initially be used to allow
those that already enable the Oslo middleware to continue to do so.
In a future release Nova reserves the right to add a /health check endpoint
that may or may not correspond to the response format defined in Oslo.
A translation between the Oslo response format and the health check module
may be provided in the future but it is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The new health check endpoint will be disabled by default.
When enabled it will not provide any authentication or explicit access control.
The documentation will detail that when enabled, the TCP endpoint should be
bound to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;localhost&lt;/span&gt;&lt;/code&gt; and that file system permission should be used to secure
the UNIX socket.&lt;/p&gt;
&lt;p&gt;The TCP configuration option will not prevent binding it to a routable IP if
the operator chooses to do so. The intent is that the data contained in the
endpoint will be non-privileged however it may contain hostnames/FQDNs or other
infrastructure information such as service UUIDs, so it should not be
accessible from the Internet.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While the health checks will use the ability to send notification as an input
to determine the health of the system, this spec will not introduce any new
notifications and as such it will not impact the Notification subsystem in
Nova. New notifications are not added as this would incur a performance
overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;At present, it is not planned to extend the Nova client or the unified client
to query the new endpoint. cURL, socat, or any other UNIX socket or TCP HTTP
client can be used to invoke the endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;We expect there to be little or no performance impact as we will be taking a
minimally invasive approach to add health indicators to key functions
which will be cached in memory. While this will slightly increase memory usage
there is no expected impact on system performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new config section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;healthcheck&lt;/span&gt;&lt;/code&gt; will be added in the nova.conf&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uri&lt;/span&gt;&lt;/code&gt; config option will be introduced to enable the health check
functionality. The config option will be a string opt that supports a
comma-separated list of URIs with the following format&lt;/p&gt;
&lt;p&gt;uri=&amp;lt;scheme&amp;gt;://[host:port|path],&amp;lt;scheme&amp;gt;://[host:port|path]&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;424242&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The URI should be limited to the following characters &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[a-zA-Z0-9_-]&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;,&lt;/span&gt;&lt;/code&gt; is reserved as a separation character, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; may only be used in IPv4
addresses, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt; is reserved for port separation unless the address is an
IPv6 address. IPv6 addresses must be enclosed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[&lt;/span&gt;&lt;/code&gt; and  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;]&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; may
be used with the UNIX protocol however relative paths are not supported.
These constraints and the parsing of the URI will be enforced and provided by
the RFC3986 lib &lt;a class="reference external" href="https://pypi.org/project/rfc3986/"&gt;https://pypi.org/project/rfc3986/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt; IntOpt will be added with a default value of 300 seconds.
If set to 0, the time to live of a health check item will be infinite.
If the TTL expires, the state will be considered unknown and the healthcheck
item will be discarded.&lt;/p&gt;
&lt;p&gt;A cache_control IntOpt will be provided to set the max-age value in the
cache_control header. By default it will have the same max-age as the TTL
config option. Setting this to 0 will disable the reporting of the header.
Setting this to -1 will report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Cache-Control:&lt;/span&gt; &lt;span class="pre"&gt;no-cache&lt;/span&gt;&lt;/code&gt;.
Any other positive integer value will be used as the max-age.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers should be aware of the new decorator and consider whether it should
be added to more functions, if that function is an indicator of the system’s
health. Failures due to interactions with external systems such as Neutron port
binding external events should be handled with caution. While failure to
receive a port binding event will likely result in the failure to boot a VM, it
should not be used as a health indicator for the nova-compute agent. This is
because such a failure may be due to a failure in Neutron, not Nova. As such,
other operations such as VM snapshot may be unaffected and the Nova compute
service may be otherwise healthy. Any failure to connect to a non-OpenStack
service such as the message bus, hypervisor, or database should be treated as a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; health indicator if it prevents the Nova binary from
functioning correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce decorator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend context object to store a reference to health check manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose TCP endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose UNIX socket endpoint support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested entirely with unit and functional tests, however,
Devstack will be extended to expose the endpoint and use it to determine
whether the Nova services have started.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The config options will be documented in the config reference
and a release note will be added for the feature.&lt;/p&gt;
&lt;p&gt;A new health check section will be added to the admin docs describing
the current response format and how to enable the feature and its intended
usage. This document should be evolved whenever the format changes or
new functionality is added beyond the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Yoga PTG topic:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415"&gt;https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 09 Nov 2022 00:00:00 </pubDate></item><item><title>Ironic Shards</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/approved/ironic-shards.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ironic-shards"&gt;https://blueprints.launchpad.net/nova/+spec/ironic-shards&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova’s Ironic driver involves a single nova-compute service managing
many compute nodes, where each compute node record maps to an Ironic node.
Some deployments support 1000s of ironic nodes, but a single nova-compute
service is unable to manage 1000s of nodes and 1000s of instances.&lt;/p&gt;
&lt;p&gt;Currently we support setting a partition key, where nova-compute only
cares about a subset of ironic nodes, those associated with a specific
conductor group. However, some conductor groups can be very large,
servered by many ironic-conductor services.&lt;/p&gt;
&lt;p&gt;To help with this, Nova has attempted to dynamically spread ironic
nodes between a set of nova-compute peers. While this work some of
the time, there are some major limitations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;when one nova-compute is down, only unassigned ironic nodes can
move to another nova-compute service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;i.e. when one nova-compute is down, all ironic nodes with nova instances
associated with the down nova-compute service are unable to be
managed, i.e. reboot will fail&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;moreover, when the old nova-compute comes back up, which might take
some time, there are lots of bugs as the hash ring slowly rebalances.
In part because every nova-compute fetches all nodes, in a large enough
cloud, this can take over 24 hours.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This spec about tweaking the way we shard Ironic compute nodes.
We need to stop violating deep assumptions in the compute manager
code by moving to a more static ironic node partitions.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Any users of the ironic driver that have more than one
nova-compute service per conductor group should move to an
active-passive failover mode.&lt;/p&gt;
&lt;p&gt;The new static sharding will be of paritcular interest for clouds
with ironic conductor groups that are greater than around
1000 baremetal nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We add a new configuration option:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;[ironic] shard_key&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, there will be no shard_key set, and we will continue to
expose all ironic nodes from a single nova-compute process.
Mostly, this is to keep things simple for smaller deployments,
i.e. when you have less than 500 ironic nodes.&lt;/p&gt;
&lt;p&gt;When the operator sets a shard_key, the compute-node process will
use the shard_key when querying a list of nodes in Ironic.
We must never try to list all Ironic nodes when
the Ironic shard key is defined in the config.&lt;/p&gt;
&lt;p&gt;When we look up a specific ironic node via a node uuid or
instance uuid, we should not restrict that to either the shard key
or conductor group.&lt;/p&gt;
&lt;p&gt;Similar to checking the instance uuid is still present on the Ironic
node before performing an action, or ensuring there is no instance uuid
before provisioning, we should also check the node is in the correct
shard (and conductor group) before doing anything with that Ironic node.&lt;/p&gt;
&lt;section id="config-changes-and-deprecations"&gt;
&lt;h3&gt;Config changes and Deprecations&lt;/h3&gt;
&lt;p&gt;We will keep the option to target a specific conductor group,
but this option will be renamed from partition_key to conductor_group.
This is addative to the shard_key above, the target ironic nodes are
those in both the correct &lt;cite&gt;shard_key&lt;/cite&gt; and the correct &lt;cite&gt;conductor_group&lt;/cite&gt;,
when both are configured.&lt;/p&gt;
&lt;p&gt;We will deprecate the use of the &lt;cite&gt;peer_list&lt;/cite&gt;.
We should log a warning when the hash ring is being used,
i.e. when it has more than one member added to the hash ring.&lt;/p&gt;
&lt;p&gt;In addtion, we need the logic that tries to move Compute Nodes
to never work unless the peer_list is larger than one. More details
in the data model impact section.&lt;/p&gt;
&lt;p&gt;When deleting a ComputeNode object, we need to have the driver
confirm that is safe. In the case of Ironic we will check to see if
the configured Ironic has a node with that uuid, searching across all
conductor groups and all shard keys. When the ComputeNode object is not
deleted, we should not delete the entry in placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="nova-manage-move-ironic-node"&gt;
&lt;h3&gt;nova-manage move ironic node&lt;/h3&gt;
&lt;p&gt;We will create a new nova-manage command:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; \
    &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This command will do the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Find the ComputeNode object for this ironic-node-uuid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if the ComputeNode type does not match the ironic driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the related Service object for the above ComputeNode
(i.e. the host)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if the service object is not reported as down, and
has not also been put into maintanance. We do not require
forced down, because we might only be moving a subset of
nodes associated with this nova-compute service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the Service object for the destination service host exists&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find all non-deleted instances for this (host,node)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error if there is more than 1 non-deleted instance found.
It is OK if we find zero or 1 instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In one DB transaction:
move the ComputeNode object to the destination service host and
move the Instance (if there is one) to the destination service host&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above tool is expected to be used as part of this wider process
of migrating from the old peer_list to the new shard key. There are
two key scearios (although the tool may help operator recover from
other issues as well):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;moving from a peer_list to a single nova-compute&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;moving from peer_list to shard_key, while keeping multiple nova-compute
proccesses (for a single conductor group)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="migrate-from-peer-list-to-single-nova-compute"&gt;
&lt;h3&gt;Migrate from peer_list to single nova-compute&lt;/h3&gt;
&lt;p&gt;Small deployments (i.e. less than 500 ironic nodes)
are recommended to move from a peer_list of, for example,
three nova-compute services, to a single nova-compute service.
On failure of the nova-compute service, operators can either manually start
the processes on a new host, or use an automatic active-passive HA scheme.&lt;/p&gt;
&lt;p&gt;The process would look something like this:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ironic and nova both default to an empty_shard key by default,
such that all ironic nodes are in the same default shard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;start a new nova-compute service running the ironic driver,
ideally with a syntheic value for &lt;cite&gt;[DEFAULT]host&lt;/cite&gt; e.g. &lt;cite&gt;ironic&lt;/cite&gt;
This will log warnings about the need to use the nova-compute
migration tool before being able to manage any nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop all existing nova-compute services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mark them as forced-down via the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now loop around all ironic nodes and call this, assuming your
nova-compute service has its host value of just &lt;cite&gt;ironic&lt;/cite&gt;:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service ironic&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The periodic tasks in the new nova-compute service will gradually
pick up the new ComputeNodes, and will start being able to recieve
commands such a reboot for all the moved instances.&lt;/p&gt;
&lt;p&gt;While you could start the new nova-compute service after
having migrated all the ironic compute nodes, but that would
lead to higher downtime during the migration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migrate-from-peer-list-to-shard-key"&gt;
&lt;h3&gt;Migrate from peer_list to shard_key&lt;/h3&gt;
&lt;p&gt;The proccess to move from the hash key based peer_list to the static
shard_key from ironic is very similar to the above process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Set the shard_key on all your ironic nodes, such that you can spread
the nodes out between your nova-compute processes,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start your new nova compute processes, one for each &lt;cite&gt;shard_key&lt;/cite&gt;,
possibly setting a synthetic &lt;cite&gt;[DEFAULT]host&lt;/cite&gt; value that matches the
&lt;cite&gt;my_shard_key&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shutdown all the older nova-compute processs with &lt;cite&gt;[ironic]peer_list&lt;/cite&gt; set&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark those older services as in maintainance via the Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each shard_key in Ironic, work out which service host you have mapped
each one to above, then run this for each ironic node uuid in the shard:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service my_shard_key&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the old services via the Nova API, now there are no instances
or compute nodes on those services&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While you could start the new nova-compute services after the migration,
that would lead to a slightly longer downtime.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="adding-new-compute-nodes"&gt;
&lt;h3&gt;Adding new compute nodes&lt;/h3&gt;
&lt;p&gt;In general, there is no change when adding nodes into existing
shards.&lt;/p&gt;
&lt;p&gt;Similarly, you can add a new nova-compute process for a new shard
and then start to fill that up with nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="move-an-ironic-node-between-shards"&gt;
&lt;h3&gt;Move an ironic node between shards&lt;/h3&gt;
&lt;p&gt;When removing nodes from ironic at the end of their life, or
adding large numbers of new nodes, you may need to rebalance
the shards.&lt;/p&gt;
&lt;p&gt;To move some ironic nodes, you need to move the nodes in
groups associated with a specific nova-compute process.
For each nova-compute and the associated ironic nodes you
want to move to a different shard you need to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Shutdown the affected nova-compute process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put nova-compute services into in maintanance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Ironic API update the shard key on the Ironic node&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now move each ironic node to the correct new nova-compute
process for the shard key it was moved into:
&lt;cite&gt;nova_manage ironic-compute-node-move &amp;lt;uuid&amp;gt; –service my_shard_key&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now unset maintanance mode for the nova-compute,
and start that service back up&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="move-shards-between-nova-compute-services"&gt;
&lt;h3&gt;Move shards between nova-compute services&lt;/h3&gt;
&lt;p&gt;To move a shard between nova-compute services, you need to
replace the nova-compute process with a new one:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ensure the destination nova-compute is configured with the
shard you want to move, and is running&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stop the nova-compute process currently serving the shard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;force-down the service via the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for each ironic node uuid in the shard call nova-manage
to move it to the new nova-compute process&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could require nova-compute processes to be explicitly forced down,
before allowing the nova-manage to move the ironic nodes about,
in a similar way to evacuate.
But this creates problems when trying to re-balance shards as you
remove nodes at the end of their life.&lt;/p&gt;
&lt;p&gt;We could consider a list of shard keys, rather than a single shard key
per nova-compute. But for this first version, we have chosen the simpler
path, that appears to have few limitations.&lt;/p&gt;
&lt;p&gt;We could attempt to keep fixing the hash ring recovery within the ironic
driver, but its very unclear what will break next due to all the deep
assumptions made about the nova-compute process. The specific assumptions
include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;when nova-compute breaks, its usually the hypervisor hardware that
has broken, which includes all the nova servers running on that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all locking and management of a nova server object is done by the
currently assigned nova-compute node, and this is only ever changed
by explict move operations like resize, migrate, live-migration
and evacuate. As such we can use simple local locks to ensure
concurrent operations don’t conflict, along with DB state checking.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A key thing we need to ensure is that ComputeNode objects are only
automatically moved between service objects when in legacy hash ring mode.
Currently, this only happens for unassigned ComputeNodes.&lt;/p&gt;
&lt;p&gt;In this new explicit shard mode, only nova-manage is able to move
ComputeNode objects. In addtion, nova-manage will also move associated
instances. However, similar to evacuate, this will only be allowed
when the currently associated service is forced down.&lt;/p&gt;
&lt;p&gt;Note, this applies when a nova-compute finds a ComputeNode that is should
own, but the Nova database says its already owned by a difference service.
In this scenario, we should log a warning to the operator
to ensure they have migrated that ComputeNode from its old location
before this nova-compute service is able to manage it.&lt;/p&gt;
&lt;p&gt;In addition, we should ensure we only delete a ComputeNode object
when the driver explictly says its safe to delete. In the case of
the Ironic driver, we should ensure the node no longer exists in
Ironic, being sure to search across all shards.&lt;/p&gt;
&lt;p&gt;This is all very related this spec on robustfying
the Compute Node and Service object relationship:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/853837"&gt;https://review.opendev.org/c/openstack/nova-specs/+/853837&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will experience a more reliable Ironic and Nova integration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;It should help users more easily support large ironic deployments
integrated with Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;We will rename the “partition_key” configuration to be expliclity
“conductor_group”.&lt;/p&gt;
&lt;p&gt;We will deprecate the peer list key. When we start up and see
anything set, we ommit a warning about the bugs in using this
legacy auto sharding, and recomend moving to the explicit sharding.&lt;/p&gt;
&lt;p&gt;There is a new &lt;cite&gt;shard_key&lt;/cite&gt; config, as descirbed above.&lt;/p&gt;
&lt;p&gt;There is a new nova_manage CLI command to move Ironic compute nodes
on forced-down nova-compute services to a new one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For those currenly using peer_list, we need to document how they
can move to the new sharding approach.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;JayF&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Feature liaison: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;rename conductor group partition key config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;deprecate peer_list config, with warning log messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add compute node move and delete protections, when peer_list not used&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add new shard_key config, limit ironic node list using shard_key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add nova-manage tool to move ironic nodes between compute services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;document operational processes around above nova-manage tool&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The deprecation of the peer list can happen right away.&lt;/p&gt;
&lt;p&gt;But the new sharding depends on the Ironic shard key getting added:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/ironic-specs/+/861803"&gt;https://review.opendev.org/c/openstack/ironic-specs/+/861803&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally we add this into Nova after robustify compute node has landed:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/842478"&gt;https://review.opendev.org/c/openstack/nova/+/842478&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We need some functional tests for the nova-manage command to ensure
all of the safty guards work as expected.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A lot of docs needed for the Ironic driver on the operational
procedures around the shard_key.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 27 Oct 2022 00:00:00 </pubDate></item><item><title>Support Napatech LinkVirtualization SmartNICs</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.2/approved/support-napatech-linkvirtualization-smartnic.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-napatech-linkvirtualization-smartnic"&gt;https://blueprints.launchpad.net/nova/+spec/support-napatech-linkvirtualization-smartnic&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Napatech LinkVirtualization SmartNICs offload network traffic switching, QoS,
and tunnel encapsulation/decapsulation functions from the OVS running on the
hypervisor to the on-board silicon. This spec proposes to update the Nova and
Neutron source code to include support for a new VIF type corresponding to the
virtual devices exposed by the LinkVirtualization SmartNIC.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Napatech SmartNICs can offload several computational resource intensive tasks
from the hypervisor, such as packet switching, QoS enforcement, and V(x)LAN
tunnel encapsulation/decapsulation. Upstream and Out of tree OVS
implementations can leverage these offloads when using dpdk via DPDK port
representors (&lt;a class="reference external" href="https://docs.openvswitch.org/en/latest/topics/dpdk/phy/#representors"&gt;https://docs.openvswitch.org/en/latest/topics/dpdk/phy/#representors&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Data processing, like encryption and compression, can be extremely intensive
when performed in software and require a tremendous amount of CPU cores.
By offloading these functions to accelerated NIC hardware it is possible
to significantly increase performance and free CPU cores to support more
virtual functions on the same server.&lt;/p&gt;
&lt;p&gt;To achive those goals Napatech provides
&lt;a class="reference external" href="https://shorturl.at/qAIL9"&gt;SmartNIC Solution Virtual Switch Acceleration&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://shorturl.at/cizAL"&gt;Napatech Getting Started Guide&lt;/a&gt; will provide details regarding
&lt;a class="reference external" href="https://shorturl.at/iS137"&gt;Napatech SmartNIC solution for hardware offload&lt;/a&gt;:
* OS Preparation
* Compiling and Installing DPDK with the Napatech PMD
* Running OVS-DPDK
* OVS-DPDK Configuration Examples&lt;/p&gt;
&lt;p&gt;Nova and os-vif currently support kernel-based VF representors, but not the
DPDK VF representors which leverage vhost-user socket. This spec seeks to
address this gap.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An end user of Napatech SmartNIC should be able to support Napatech SmartNICs
out-of-the-box.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other SmartNICs using OvS-DPDK representor ports should also work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We propose to extend the OpenvSwitch driver with a new VNIC type
&lt;cite&gt;VNIC_VIRTIO_FORWARDER&lt;/cite&gt; and the related VIF handling function
&lt;cite&gt;nova_to_osvif_vif()&lt;/cite&gt;. A method which handles vhostuser VIF type should
handle the new VNIC type by setting an appropriate datapath, representor port
profile, vhostuser vif type, &lt;cite&gt;OVS&lt;/cite&gt; plugin, and datapath offload settings.
OpenvSwitch driver should be able to set the DPDK representor socket path for
virtio-forwarder vnic type:
&lt;a class="reference external" href="https://docs.openvswitch.org/en/latest/topics/dpdk/phy/#representors"&gt;https://docs.openvswitch.org/en/latest/topics/dpdk/phy/#representors&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We propose to extend vif type &lt;cite&gt;OVS&lt;/cite&gt; attribute &lt;cite&gt;OVS_DPDK_PORT_TYPES&lt;/cite&gt; with a
new port type &lt;cite&gt;dpdk&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We propose to update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OvsPlugin&lt;/span&gt;&lt;/code&gt; class to support plug and unplug of
OVS DPDK representor ports &lt;a class="reference external" href="https://encr.pw/uSQfn"&gt;os_vif OVSPlugin code&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Appropriate methods &lt;cite&gt;plug()&lt;/cite&gt; and &lt;cite&gt;unplug()&lt;/cite&gt; should be extended with
ability to plug VF if vif has &lt;cite&gt;VIFPortProfileOVSRepresentor&lt;/cite&gt; port profile for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIFVHostUser&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;_plug_vf()&lt;/cite&gt; method should be extended with formula &lt;cite&gt;VF_NUM=ID*8+VF&lt;/cite&gt; to
calculate VF number based on the input PCI slot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;update_device_mtu()&lt;/cite&gt; method will be extended with &lt;cite&gt;OVS_DPDK_INTERFACE_TYPE&lt;/cite&gt;
interface support to have ability update MTU configuration for port on the
OVS layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We propose Unit/Functional tests pertinent to the proposed changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://www.napatech.com/products/nt200a02-smartnic-capture/"&gt;NT200A02&lt;/a&gt; and &lt;a class="reference external" href="https://www.napatech.com/products/nt50b01-smartnic-capture/"&gt;NT50B01&lt;/a&gt; SmartNics with Link-Virtualization™ software
will provide support of the hardware-based solution for full
Open vSwitch (OVS) offload.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Napatech will a provide document with NT NIC hardware offloading
configuration in the OpenStack. This documentation will consist
configuration steps, requirements, links on the Napatech portal
with software and additional specific documentations. This document
will be created under Neutron project.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Users will see a significant network performance increase when running over
the hardware offloaded data-plane compared kernel-ovs and traditional
vhost-user.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In line with other SmartNIC offerings, the deployer will have to configure
OVS-DPDK following the SmartNIC producer guidelines and update the PCI
device_spec configuration.
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#pci.device_spec"&gt;https://docs.openstack.org/nova/latest/configuration/config.html#pci.device_spec&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Oleksii Butenko (obu-plv)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Danylo Vodopianov (dvo-plv)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Justas Poderys (justas_napa on IRC and Gerrit)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Sean Mooney (sean-k-mooney)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend Openvswitch driver with Virtio-Forwarder VIF type support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add Virtio-Forwarder VIF type for Qos support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new OVS datapath port type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dpdk&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add ability to set MTU for dpdk representor potr type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add ability to plug vf with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIFPortProfileOVSRepresentor&lt;/span&gt;&lt;/code&gt; vif profile
for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIFVHostUser&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add/Update Unit and Functional tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This blueprint is a prerequisite to update code in Neutron to support
LinkVirtualization SmartNICs. This is in-line with support of other
SmartNICs. Links to changes of all four components are given in the Work
Items section.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Code changes will require additional testing coverage:
*  New unit tests will be implented or updated existing.
*  New functional tests will be implemented.
*  Napatech will provide third party ci for testing on the NT hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We are not introducing any new VNIC type, so there should be no impact on
documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Napatech LinkVirtualization:
&lt;a class="reference external" href="https://www.napatech.com/products/link-virtualization-software/"&gt;https://www.napatech.com/products/link-virtualization-software/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Napatech SmartNIC solution for hardware offload
&lt;a class="reference external" href="https://shorturl.at/iS137"&gt;https://shorturl.at/iS137&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Napatech Getting Started Guide
&lt;a class="reference external" href="https://shorturl.at/cizAL"&gt;https://shorturl.at/cizAL&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.2 Bobcat&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 26 Sep 2022 00:00:00 </pubDate></item><item><title>Remove the API support for generating a keypair</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/implemented/keypair-generation-removal.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/keypair-generation-removal"&gt;https://blueprints.launchpad.net/nova/+spec/keypair-generation-removal&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As agreed on the last PTG, given RSA-SHA1 support is removed from recent OSes,
we prefer to remove the possibility to generate a keypair directly by Nova and
just be able to import a public key.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;During the Yoga release, we triaged an open bug report &lt;a class="footnote-reference brackets" href="#id6" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; which noted
the fact that OpenSSH 8.8 removed support for RSA/SHA1 signatures
&lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. As a result of this change in OpenSSH behavior, keypairs generated by
Nova are incompatible with recent guest OSes like CentOS9.
This leads to guests that are inaccessible via SSH using the created keypairs.&lt;/p&gt;
&lt;p&gt;The consensus of the Nova community during the last PTG was to remove the
generation of keypairs from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-keypairs&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I want to ssh to my instance without getting problems because I
generated a keypair.&lt;/p&gt;
&lt;p&gt;As an admin, I want a seamless experience for my users and I let them to
generate their own keypairs depending on the images they want.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We’ll propose a new API microversion that will force the user to send a
public key.&lt;/p&gt;
&lt;p&gt;Accordingly, the JSON request schema of POST /os-keypairs will look like this :&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;create_v2XX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'keypair'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;parameter_types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'enum'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ssh'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'x509'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'public_key'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'public_key'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'keypair'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The JSON response will also change as we no longer generate private keys :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private_key&lt;/span&gt;&lt;/code&gt; will never be returned from that microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given we’ll create a new microversion, we’ll also use it for allowing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt; &lt;span class="pre"&gt;(dot)&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@&lt;/span&gt; &lt;span class="pre"&gt;(at)&lt;/span&gt;&lt;/code&gt; characters for the keypair name as it was accepted
on a previous spec for Xena &lt;a class="footnote-reference brackets" href="#id8" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This will mean that we will modify the _validate_new_key_pair() method to
accept those parameters only if wanted (which also means we will move this
method to the keypairs specific API module).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;For API interoperability reasons, we would have had to also create a new API
microversion if we wanted to support a new keypair type, eg. edcsa, which
defeats the purpose of simplicity.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;All the details are already described above. The response will only drop the
meaningless private_key value as we continue to return a keypair with its
signature.
No policy changes are identified, as we only drop support for a capability.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;We’ll improve security, for sure, by not letting Nova to create keypairs that
are disabled by OS policy due to the flaws of SHA-1 (even if ssh-rsa can
verify keys with SHA-256 hash algorithm) &lt;a class="footnote-reference brackets" href="#id9" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;novaclient and openstackclient new releases will remove support for generating
a keypair if you opt-in for the recent server microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sylvain-bauza&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;write the API change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amend documentation and tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;write novaclient, openstacksdk and openstackclient support for this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unittests for sure, but we’ll also need to modify Tempest to generate
the keypair by itself and import it into Nova. Thanks to the FIPS support we
already have, a conditional in Tempest already pre-generates a keypair and
tampers the payload by adding the generated public key &lt;a class="footnote-reference brackets" href="#id10" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, so we should just
make it default in our upstream jobs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None, besides API documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1962726"&gt;https://bugs.launchpad.net/nova/+bug/1962726&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/li&gt;
&lt;li&gt;&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.openssh.com/txt/release-8.8"&gt;https://www.openssh.com/txt/release-8.8&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/li&gt;
&lt;li&gt;&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/allow-special-characters-in-keypair-name.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/allow-special-characters-in-keypair-name.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/li&gt;
&lt;li&gt;&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;“SHA-1 is a Shambles: First Chosen-Prefix Collision on SHA-1 and
Application to the PGP Web of Trust” Leurent, G and Peyrin, T
(2020) &lt;a class="reference external" href="https://eprint.iacr.org/2020/014.pdf"&gt;https://eprint.iacr.org/2020/014.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/li&gt;
&lt;li&gt;&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/tempest/blob/c545cb1c7c14d36d2bc65a55ec13e0c6cd095425/tempest/lib/services/compute/keypairs_client.py#L81-L88"&gt;https://github.com/openstack/tempest/blob/c545cb1c7c14d36d2bc65a55ec13e0c6cd095425/tempest/lib/services/compute/keypairs_client.py#L81-L88&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id11"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 06 Sep 2022 00:00:00 </pubDate></item><item><title>Add Virtual IOMMU device support for libvirt driver</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/implemented/libvirt-viommu-device.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-viommu-device"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-viommu-device&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec adds support to expose a virtual IO memory mapping unit (vIOMMU) with
libvirt driver.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently it is possible to use libvirt to expose vIOMMU to a guest when using
the x86 Q35 or ARM virt machine types. On some platfroms such as AArch64 an
vIOMMU is required to fully support PCI passthough and in general it can enable
use of vfio-pci in guests that require it. Nova does not currently expose
vIOMMU functionality to operators or users.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator deploying nova on aarch64, I would like to be able to leverage
PCI passthrough to support assigning accelerators and other PCIe devices to
my guests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I would like to enable my end users to use dpdk in their vms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a vnf vendor, that delivers applications that leverage accelerators that
require an iommu I would like to express that as an attribute of the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I would like to nova to expose vIOMMU capability on a host
that supports it and automatically place vms that requires it on appropriate
hosts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This spec proposes adding new guest configs for
IOMMU (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigGuestIOMMU&lt;/span&gt;&lt;/code&gt;) and
APIC feature (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigGuestFeatureIOAPIC&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add following attribute to image property and extra_specs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_viommu_model&lt;/span&gt;&lt;/code&gt; (for image property) and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:viommu_model&lt;/span&gt;&lt;/code&gt; (for extra_specs):
Support values none|intel|smmuv3|virtio|auto. Default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt;.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auto&lt;/span&gt;&lt;/code&gt; will select &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio&lt;/span&gt;&lt;/code&gt; if Libvirt supports it,
else &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;intel&lt;/span&gt;&lt;/code&gt; on X86 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smmuv3&lt;/span&gt;&lt;/code&gt; on AArch64.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;above attribute is on of options for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigGuestIOMMU&lt;/span&gt;&lt;/code&gt;, More
information for them can be found in &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#iommu-devices"&gt;libvirt format domain&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add IOMMU config when generating guest config. And enable IOAPIC within.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_locked_memory&lt;/span&gt;&lt;/code&gt; for image property and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:locked_memory&lt;/span&gt;&lt;/code&gt; for
extra specs. This will make sure &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked&lt;/span&gt;&lt;/code&gt; element is present in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memoryBacking&lt;/span&gt;&lt;/code&gt;, but only allow it if you have also set
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt;, so we can ensure that the scheduler can actually
account for this correctly and prevent out of memory events.
Here is a reference to related issue &lt;a class="reference external" href="https://listman.redhat.com/archives/vfio-users/2018-July/msg00001.html"&gt;MEMLOCK_RLIMIT&lt;/a&gt;.
Locked memory not only disables memory over subscription but it also prevent
the kernel form swapping the memory.
Enable this will disable the RLIMITs for the VM in cases where you have a
large number of passed through devices.
When assigning multiple devices to the same VM. The issue is that with a
guest IOMMU, each assigned device has a separate address space that is
initially configured to map the full address space of the VM and each
vfio container for each device is accounted separately. Libvirt will only
set the locked memory limit to a value sufficient for locking the memory
once, whereas in this configuration we’re locking it once per assigned
device. Without a guest IOMMU, all devices run in the same address space
and therefore the same container, and we only account the memory once for
any number of devices (with  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; set to any value this will
enable the NUMA toplogy fitler to schdule based on the fact the memory can’t
be over commited).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;aw_bits&lt;/span&gt;&lt;/code&gt; attribute in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigGuestIOMMU&lt;/span&gt;&lt;/code&gt;:
This attribute can used to set the address width to allow mapping larger iova
addresses in the guest. Since 6.5.0 (QEMU/KVM only).
As Qemu current supported values are 39 and 48, I propose we set this to
larger width (48) by default and will not exposed to end user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eim&lt;/span&gt;&lt;/code&gt; attribute in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigGuestIOMMU&lt;/span&gt;&lt;/code&gt;:
this will not exposed to end user, but will directly enabled if machine type
is Q35.
Side Note:
eim(Extended Interrupt Mode) attribute (with possible values on and off)
can be used to configure Extended Interrupt Mode.
A q35 domain with split I/O APIC (as described in hypervisor features),
and both interrupt remapping and EIM turned on for the IOMMU, will be
able to use more than 255 vCPUs. Since 3.4.0 (QEMU/KVM only).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide iommu model trait for each viommu model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_viommu_model&lt;/span&gt;&lt;/code&gt; to request_filter, this will extend the
transform_image_metadata prefilter to select host with the correct model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide new compute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_IOMMU_MODEL_*&lt;/span&gt;&lt;/code&gt; capablity trait for each model
it supports in driver.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Enable vIOMMU might introduce significant performance overhead.
You can see performance comparision table from
&lt;a class="reference external" href="https://static.sched.com/hosted_files/kvmforum2021/da/vIOMMU%20KVM%20Forum%202021%20-%20v4.pdf"&gt;AMD vIOMMU session on KVM Forum 2021&lt;/a&gt;.
For above reason, vIOMMU should only be enable for workflow that require it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators will see new extra spec options and image properties.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfin&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ricolin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new guest configs: &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/830646"&gt;https://review.opendev.org/c/openstack/nova/+/830646&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs for new guest options in extra_specs and image properties.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit test for in patch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can work on more advance test against real environment.
Not that needed for this patch IMO but we still should provide certain level
of examine for extra guarantee.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New docs for new guest options in extra_specs and image properties
documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;patch: &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/830646"&gt;https://review.opendev.org/c/openstack/nova/+/830646&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AMD vIOMMU session on KVM Forum 2021: &lt;a class="reference external" href="https://static.sched.com/hosted_files/kvmforum2021/da/vIOMMU%20KVM%20Forum%202021%20-%20v4.pdf"&gt;https://static.sched.com/hosted_files/kvmforum2021/da/vIOMMU%20KVM%20Forum%202021%20-%20v4.pdf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 06 Sep 2022 00:00:00 </pubDate></item><item><title>Allow unshelve to a specific host</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/implemented/unshelve-to-host.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unshelve-to-host"&gt;https://blueprints.launchpad.net/nova/+spec/unshelve-to-host&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to allow administrator to specify &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;
to unshelve a shelved offloaded server.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, an instance can only be unshelved to a specific availability zone.
The proposal is to extend the unshelve behavior allowing an instance to be
unshelved to a specific host.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a PROJECT_ADMIN, I want to specify a destination host when executing
unshelve on a shelved-offloaded instance.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to extend the unshelve API behavior to support a
specific destination host.&lt;/p&gt;
&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; attribute to POST /server/uuid/action for unshelve request body.&lt;/p&gt;
&lt;p&gt;Add 2 checks:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ensure the user is a PROJECT_ADMIN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the instance state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shelved_offloaded&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the introduction of the new microversion, change the scheduling and
request specification (reqspec) behaviors of the unshelve API.&lt;/p&gt;
&lt;p&gt;Current behavior:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Boot&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Unshelve after offload&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Result&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Free scheduling, reqspec.AZ kept None&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule in the AZ, update reqspec.AZ
to the requested one&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;With AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule in original AZ, keep reqspec
pointing that AZ&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;With AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule to the new AZ, update the
reqspec.AZ to the new AZ&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Proposed new behavior:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Boot&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Unshelve after offload AZ&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Host&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Result&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No AZ or AZ=null&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Free scheduling,
reqspec.AZ=None&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No AZ or AZ=null&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Host1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule to host1,
reqspec.AZ=None&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ=”AZ1”&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule to AZ1,
reqspec.AZ=”AZ1”&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ=”AZ1”&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Host1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Verify that host1 in AZ1,
or (3). Schedule to
host1, reqspec.AZ=”AZ1”&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;AZ1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule to AZ1,
reqspec.AZ=”AZ1”&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;AZ1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ=null&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Free scheduling,
reqspec.AZ=None&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;AZ1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No AZ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Host1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;If host1 is in AZ1,
then schedule to host1,
reqspec.AZ=”AZ1”, otherwise
reject the request (1)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;AZ1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ=null&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Host1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule to host1,
reqspec.AZ=None&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;AZ1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ=”AZ2”&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Schedule to AZ2,
reqspec.AZ=”AZ2”&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;AZ1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;AZ=”AZ2”&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Host1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;If host1 in AZ2 then
schedule to host1,
reqspec.AZ=”AZ2”,
otherwise reject (1)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Check at the api and return an error.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The current proposal rejects unshelve to a specific host if the instance state
is not shelved_offloaded.
Alternatively, a request to unshelve to a specific host would change the
instance state to shelved_offloaded automatically. So the user would not have
to worry about the initial instance state.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Change the validation schema allowing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone=null&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt;.
An error in schema validation will raise a HTTP400.&lt;/p&gt;
&lt;p&gt;Ensure the instance state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shelved_offloaded&lt;/span&gt;&lt;/code&gt;.
An error in such case will rise a HTTP409.&lt;/p&gt;
&lt;p&gt;Starting from the new API microversion, the
POST &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt;
API can be called with the following body:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: null}   (Keep compatibility with previous microversions)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“availability_zone”: &amp;lt;string&amp;gt;}}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“availability_zone”: null}}   (Unpin availability zone)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“host”: &amp;lt;fqdn&amp;gt;}}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“availability_zone”: &amp;lt;string&amp;gt;, “host”: &amp;lt;fqdn&amp;gt;}}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“availability_zone”: null, “host”: &amp;lt;fqdn&amp;gt;}}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything else is not allowed, examples:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {}}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“host”: &amp;lt;fqdn&amp;gt;, “host”: &amp;lt;fqdn&amp;gt;}}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;{“unshelve”: {“foo”: &amp;lt;string&amp;gt;}}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-openstackclient&lt;/span&gt;&lt;/code&gt; will be updated and will provide support for
the new microversion.&lt;/p&gt;
&lt;p&gt;A new switch &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--unpin-az&lt;/span&gt;&lt;/code&gt; will be introduced to the unshelve command allowing
PROJECT_ADMIN to remove the availability zone constraint of a server.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;python-novaclient&lt;/span&gt;&lt;/code&gt; will just be extended with the python helper
functions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sbauza&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new microversion to the unshelve to a specific host
(unshelve Action) API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a tempest test&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API reference and the unshelve documentation will be updated to explain
the new behavior introduced by the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 06 Sep 2022 00:00:00 </pubDate></item><item><title>volume-backed server rebuild</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/implemented/volume-backed-server-rebuild.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/volume-backed-server-rebuild"&gt;https://blueprints.launchpad.net/nova/+spec/volume-backed-server-rebuild&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, the compute API will &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/e44b1a940fdc45cc9dbb08e193a8c25052cf64e7/nova/compute/api.py#L3617-L3626"&gt;fail&lt;/a&gt; if a user tries to rebuild
a volume-backed server with a new image. This spec proposes to add
support for rebuilding a volume-backed server with a new image.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Nova rebuild (with a new image) only supports instances which are
booted from images. The volume-backed instance cannot be rebuilt when a new
image is supplied. Trying to rebuild a volume-backed instance will raise a
HTTPBadRequest exception.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user, I would like to rebuild my volume-backed server with a new image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;First, change the existing API for rebuilding a volume-backed server.
Then the API flow would be:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A new microversion will be required to opt into the new functionality.
If it is old API microversion request, then it should be 400 returned.
Note that the old behaviour still allows to rebuild a volume backed
server with the same image in which we don’t wipe out the data of the
volume so to prevent the user from accidently destroying all their data,
we require them to use the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the cinder microversion is new enough to support reimage
the boot volume. If not, will raise CinderAPIVersionNotAvailable
exception.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In case of multiattach volumes, n-api will reject the request since
rebuilding multiattach volumes require complex attachment handling and
the effort would outweigh the benefit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then the nova-compute manager will perform the following steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create an empty (no connector) volume attachment for the volume and
server. This ensures the volume remains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt;&lt;/code&gt; through the next
step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the existing volume attachment (the old one).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the new attachment UUID to the BDM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The above two steps are needed to keep the volume in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt;&lt;/code&gt; state
as a management state which is required by cinder to perform re-image
operation on it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-reimage&lt;/span&gt;&lt;/code&gt; cinder API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new ‘volume-reimaged’ external event to wait for cinder to
complete the reimage. Like we use for volume-extend.
See &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/454322"&gt;perform_resize_volume_online&lt;/a&gt; for details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After successful completion of the re-image operation, cinder will notify
Nova via external events API that the reimage operation is completed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call cinder to Update the empty volume attachment by passing the connector
info and cinder will return connection info to Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After Nova completes the connection with brick, complete the attachment
marking the volume &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this process, there are some conditions that we could hit:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If we failed to re-image the volume and the volume is in ‘error’ status
then we should set the instance status as “error”. Since users can rebuild
instances in error status, the user has a way to retry the rebuild once
the cause of the cinder side failure is resolved. Note that nova-compute
will &lt;em&gt;not&lt;/em&gt; attempt to update the volume attachment records with the host
connector again on the volume in error status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the cinder API itself returns a &amp;gt;=400 error, nothing changed about the
root volume and in that case the instance action should be ‘failed’ and the
instance status should go back to what it was (we can see how
_error_out_instance_on_exception is used).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The main alternative is that nova would perform the rebuild like an initial
boot from volume where nova-compute would create a new volume from the new
image and then replace the root volume on the instance during rebuild.&lt;/p&gt;
&lt;p&gt;There are issues with this, however, like what to do about the old volume:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Regarding ‘delete_on_termination’ flag in the BDM,
delete_on_termination=True means: delete the volume when we kill
the instance. Rebuild means: re-initialize this instance in place. The
rebuild flow would have to determine what to do if the old root volume
BDM was marked with delete_on_termination=True. If delete_on_termination
is True, delete the old root volume, otherwise, preserve it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could pass a new flag to the rebuild API telling nova what to do about the
old volume (delete it or not).
If the flag is true to delete the old volume but the old volume has
snapshots, Nova won’t be deleting the volume snapshots just to delete
the volume during a rebuild.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are several issues with that as mentioned above like quota and
the questions about what nova should do about the old volume, you can
see more detailed information in &lt;a class="reference internal" href="#references"&gt;References&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Change the rebuild request response code from 400 to 202 if the conditions
described in the &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt; section are met.
The API microversion and compute RPC version will also be incremented to
indicate the new support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The python-novaclient and python-openstackclient will be updated to support
the new microversion.
Two additional parameters &lt;cite&gt;–reimage-boot-volume`&lt;/cite&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--no-reimage-boot-volume&lt;/span&gt;&lt;/code&gt; will be added as a check (along with the
microversion check) on the OpenStackClient side that will determine if
the user really knows it will reimage the volume.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The operation will take longer because of the external dependency
involved and the work that needs to happen in Cinder.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If the cinder volume &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reimage&lt;/span&gt;&lt;/code&gt; API operation fails and the volume goes to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; status, an admin will likely need to investigate and resolve the
issue in cinder and then reset the volume status to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The API microversion and compute service version will also be incremented
to indicate the new support, therefore users will not be able to leverage
the feature until the nova-compute service hosting a volume-backed instance
is upgraded.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Rajat Dhasmana &amp;lt;&lt;a class="reference external" href="mailto:rajatdhasmana%40gmail.com"&gt;rajatdhasmana&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt; (whoami-rajat)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--confirm-reimage&lt;/span&gt;&lt;/code&gt; on the client side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the existing rebuild API to allow volume backed instance rebuild with
a new image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an empty attachment for the root volume so the volume
remains in-use during rebuild (we do this today already).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the old volume attachment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call the cinder API to re-image the volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update and complete the volume attachment once re-imaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adopt the new compute version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adopt the new microversion in python-novaclient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adopt the new microversion in python-openstackclient.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Depends on the cinder blueprint for re-imaging a volume, see
more detail information in References.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The following tests are added.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova unit tests for negative scenarios&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova functional tests for “happy path” testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest integration tests to make sure the nova/cinder integration
works properly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We will replace the &lt;a class="reference external" href="https://developer.openstack.org/api-ref/compute/?expanded=#rebuild-server-rebuild-action"&gt;note in the API reference&lt;/a&gt; with
a note about the required minimum microversion for rebuilding a
volume-backed server with a new image.&lt;/p&gt;
&lt;p&gt;The following document will be updated:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API Reference&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We also need to mention in the documentation that when the volume
is re-imaged, all current content on the volume will be &lt;em&gt;destroyed&lt;/em&gt;.
This is important as cinder volumes are considered to be persistent,
which is not the case with this operation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stein PTG etherpad: &lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-ptg-stein"&gt;https://etherpad.openstack.org/p/nova-ptg-stein&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is the discussion about rebuild the volume-backed server:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2017-October/123255.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2017-October/123255.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is the discussion about what we should do about the root volume
during a rebuild:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-operators/2018-March/014952.html"&gt;http://lists.openstack.org/pipermail/openstack-operators/2018-March/014952.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The cinder blueprint for re-imaging a volume:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/cinder/+spec/add-volume-re-image-api"&gt;https://blueprints.launchpad.net/cinder/+spec/add-volume-re-image-api&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions
   :header-rows: 1&lt;/span&gt;&lt;/caption&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 06 Sep 2022 00:00:00 </pubDate></item><item><title>PCI Device Tracking In Placement</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/pci-device-tracking-in-placement.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pci-device-tracking-in-placement"&gt;https://blueprints.launchpad.net/nova/+spec/pci-device-tracking-in-placement&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The OpenStack Placement service was designed to provide tracking
of quantitative resources via resource class inventories and qualitative
characteristics via traits. Over the last few cycles, nova has utilized
Placement to track basic resources such as CPUs, RAM, and disk, and more
complex resources such as Virtual GPUs. This spec describes how Nova can
utilize Placement to track generic PCI devices without going into the details
of the NUMA awareness of such devices.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova has supported generic stateless PCI passthrough for many releases using a
dedicated PCI tracker in conjunction with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; scheduler
post filter.&lt;/p&gt;
&lt;p&gt;The PCI tracker is responsible for tracking which PCI devices are available,
claimed, and allocated, the capabilities of the device, its consumer when
claimed or allocated as well as the type of PCI device and location.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; is responsible for ensuring that devices,
requested by the VM, exist on a host during scheduling. These PCI requests come
from two sources: flavor-based PCI requests that are generated using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough:alias&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/extra-specs.html#pci_passthrough:alias"&gt;flavor extra specs&lt;/a&gt; and neutron based PCI requests
generated from SR-IOV backed neutron ports.&lt;/p&gt;
&lt;p&gt;While the current approach to PCI tracking works there are some limitations
in the current design and there is room for optimization.&lt;/p&gt;
&lt;p class="rubric"&gt;Limitations&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;During server creation PCI devices are not claimed until the instance_claim
is created on the compute node. As a result, it is possible for two
concurrent server create requests to race for the last device on a host
resulting in re-schedules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While Nova today tracks the capabilities of network interfaces in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_devices&lt;/span&gt;&lt;/code&gt; table and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; could match on those capabilities there is no
user-facing way to express a request for an SR-IOV neutron port with a
specific network capability e.g. TSO.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no admin-facing interface to check the available and allocated PCI
resources in the cloud. The only way is to look into the Nova database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Optimizations&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Today when the virt driver is assigning a PCI device on the compute hosts
it needs to look at all available PCI devices on the host and select one that
fulfills the PCI and NUMA requirements. If we model PCI devices in Placement
we only need to consider the devices associated with the PCI resource
allocation in Placement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Today when we schedule we perform host filtering of viable hosts based on
PCI devices in python. By utilizing Placement we can move that filtering to
SQL.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want instance creation to atomically claim resources to
decrease the chance of retries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to shorten the time it takes to select a host by
running fewer filters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to utilize traits and resource classes to model
PCI aliases and requests for more expressive device management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to be able to associate quotas with PCI device usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to be able to use the Placement API to query available
and allocated PCI devices in my cloud.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Device quotas would require unified limits to be implemented. Implementing
quotas is out of the scope of this spec beyond enabling the use case by
modeling PCI devices in Placement.&lt;/p&gt;
&lt;p&gt;This spec will also only focus on flavor-based PCI passthrough. Neutron
SR-IOV port will be addressed in a follow-up spec to limit the scope.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="opt-in-reporting-of-pci-devices-in-placement"&gt;
&lt;h3&gt;Opt-in reporting of PCI devices in Placement&lt;/h3&gt;
&lt;p&gt;To support upgrade of existing deployments with PCI passthrough configured
and to be able to deprecate and eventually remove some of the functionality of
the current PCI device tracker the new Placement based PCI device tracking will
be disabled by default in the first release. The new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; config option can be used to enable the
functionality. It will be defaulted to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; first and once it is turned to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; nova-compute will refuse to start if disabled again. In a future
release, after the PCI tracking in Placement is feature complete, the default
will be changed to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="pci-device-spec-configuration"&gt;
&lt;h3&gt;PCI device_spec configuration&lt;/h3&gt;
&lt;p&gt;Below we propose a change to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; configuration
option. While we are making this change we will take this opportunity to
update the name of the configuration option. The old name of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; config option will be deprecated for eventual
removal and a new name &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; will be added. Both the
old and the new name will support the newly proposed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;p&gt;The syntax of the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#pci.passthrough_whitelist"&gt;PCI passthrough device list&lt;/a&gt; configuration option will be
extended to support two additional standard tags &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt;. These new tags will only take effect if the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; config option is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-js notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nx"&gt;device_spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"vendor_id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1002"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"67FF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"resource_class"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_GPU"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"traits"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_RADEON_RX_560"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_GDDR5"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;device_spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:82:00.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"resource_class"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_FPGA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"traits"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM_XILINX_XC7VX690T"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; tag will be accepted only when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt;
tag is not defined and will enable a PCI device to be associated with a custom
resource class. Each PCI device_spec entry may have at most one resource class
associated with it. Devices that have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag will not be
reported in Placement at this time as Neutron based SR-IOV is out of the
scope of the current spec.&lt;/p&gt;
&lt;p&gt;Where a PCI device does not have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; or a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt;
tag present it will be reported with a generated custom resource class.
The resource class will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PCI_&amp;lt;vendor_id&amp;gt;_&amp;lt;product_id&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag will be a comma-separated list of standard or custom trait
names that will be reported for the device RP in Placement.&lt;/p&gt;
&lt;p&gt;Nova will normalize and prefix the resource class and trait names with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_&lt;/span&gt;&lt;/code&gt;, if it isn’t already prefixed, before creating them in Placement.
Nova will first check the provided trait name in os_traits and if it exists
as a standard trait then that will be used instead of creating a custom one.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Initially traits will only be additive, in the future if we need to we can
allow traits to be removed using a +/- syntax but this is not included
in the scope of this spec.&lt;/p&gt;
&lt;p&gt;As detailed in the &lt;a class="reference internal" href="#modeling-pci-devices-in-placement"&gt;Modeling PCI devices in Placement&lt;/a&gt; section, each
physical device (PF) will be its own resource provider with inventories of
the relevant PF and VF resource classes. As such traits cannot vary per VF
device under the same parent PF. If VFs are individually matched by different
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entries, then defining different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt;  for different
VFs under the same PF is a configuration error and will be rejected.&lt;/p&gt;
&lt;p&gt;While it would possible to support defining different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt;
names for different VFs under the same parent PF, this is considered bad
practice and unnecessary complexity. Such configuration will be rejected.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Nova will detect if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; configuration of
an already reported device is changed at a nova-compute service restart. If
the affected device is free then Nova will apply the change in Placement. If
the device is allocated then changing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; would result in
removing of existing allocations which is rejected by placement and therefore
the compute service will refuse to start.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In the future when PCI tracking in Placement will be extended to device_spec
entries with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag, these entries will not allow
specifying a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; but nova will use the standard
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SRIOV_NET_VF&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VDPA_NETDEV&lt;/span&gt;&lt;/code&gt; classes. This will
not prevent type-VF and type-PF devices to be consumed via PCI alias, as the
alias can request these standard resource classes too.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The new Placement based PCI tracking feature won’t support the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; tag
in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; configuration. Usage of this tag is already limited
as not all PCI devices has a device name. Also &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; only works
properly if the names are kept stable across hypervisor reboots and upgrades.
If the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; has any entry with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; tag then the nova-compute
service will refuse to start.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="modeling-pci-devices-in-placement"&gt;
&lt;h3&gt;Modeling PCI devices in Placement&lt;/h3&gt;
&lt;p&gt;PCI device modeling in Placement will closely mirror that of vGPUs.
Each PCI device of type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PCI&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PF&lt;/span&gt;&lt;/code&gt; will be modeled as a
Placement resource provider (RP) with the name
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;hypervisor_hostname&amp;gt;_&amp;lt;pci_address&amp;gt;&lt;/span&gt;&lt;/code&gt;. The hypervisor_hostname prefix will be
the same string as the name of the root RP. The pci_address part of the
name will be the full PCI address in the same format of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DDDD:BB:AA.FF&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The pGPU RPs are using the libvirt nodedev name but this spec is not try to
follow that naming scheme as the libvirt nodedev names are not considered
stable. Also nova always uses the RP UUID to identify and RP instead of its
name. So these names are only for troubleshooting purposes.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Each PCI device RP will have an inventory of resource class and traits based
on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; entry matching with the given device. If the device
has children devices (VFs) matching with any &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry then the
resource inventory and traits of the children will be reported to the parent PF
RP too.&lt;/p&gt;
&lt;p&gt;If a PCI device is matching a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry without a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag then an inventory of 1 is reported of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; specified in the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry or if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; is not specified there then with the generated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PCI_&amp;lt;vendor_id&amp;gt;_&amp;lt;product_id&amp;gt;&lt;/span&gt;&lt;/code&gt; resource class.&lt;/p&gt;
&lt;p&gt;If a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-VF&lt;/span&gt;&lt;/code&gt; device is matching a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry then the related
resource inventory will be reported on RP representing its parent PF device.
The PF RP will be created even if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PF&lt;/span&gt;&lt;/code&gt; device is not matching any
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry but in that case, only VF inventory will exist on the RP.&lt;/p&gt;
&lt;p&gt;If multiple VFs from the same parent PF is matching the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; then
the total resource inventory of VFs will be the total number of matching VF
devices.&lt;/p&gt;
&lt;p&gt;Each PCI device RP will have traits reported according to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag
of the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; entry. Additionally, Nova will report the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MANAGED_PCI_DEVICE&lt;/span&gt;&lt;/code&gt; standard trait on the device RPs automatically.
This is used by the nova-compute service to reject a reconfiguration where
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is disable after it was enabled.&lt;/p&gt;
&lt;p&gt;Listing both the parent PF device and any of this children VF devices at the
same time will not be support if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is enabled. See
&lt;a class="reference internal" href="#dependent-device-handling"&gt;Dependent device handling&lt;/a&gt; section for more details.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Even though neutron-requested PCI devices are out of the scope of this spec
the handling of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-PF&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-VF&lt;/span&gt;&lt;/code&gt; devices cannot be ignored as
those device types can also be requested via PCI alias by setting the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_type&lt;/span&gt;&lt;/code&gt; tag accordingly.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The PCI alias can only request devices based on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt; today and that information will be automatically included in
the Placement inventory as the resource class.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In the future Nova can be extended to automatically report PCI device
capabilities as custom traits in placement. However this is out of scope of
the current spec. If needed the deployer can add these traits via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; configuration manually.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="reporting-inventories-from-the-resourcetracker-to-placement"&gt;
&lt;h3&gt;Reporting inventories from the ResourceTracker to Placement&lt;/h3&gt;
&lt;p&gt;The ResourceTracker and the PciDevTracker implements a virt driver agnostic
PCI device inventory and allocation handling. This logic is extended to
provide PCI inventory information to Placement by translating PciDevice and
PciDeviceSpec objects to Placement resource providers, resource inventories,
and traits.&lt;/p&gt;
&lt;p&gt;This new translator logic is also capable of healing missing PCI resource
allocations of existing instances based on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; field of the
allocated PciDevice objects. The missing allocations will be created in
Placement via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/reshape&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;To aid the PCI scheduling via placement this logic also records the UUID of the
resource provider representing a PCI device into the PciDevice object. Then
the existing PCI pooling logic will translate such mapping to a PCI device
pool, resource provider UUID mapping. Note that the scheduler needs one to one
mapping between resource provider and PCI device pool, so the PCI pooling logic
is changed to represent each type-PCI and PF devices as separate pools and only
pool together VFs from the same parent PF to the same Pool.&lt;/p&gt;
&lt;p&gt;The inventory and allocation handling logic will run in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource&lt;/span&gt;&lt;/code&gt; periodic as well as during resource tracked
update due to instance actions.&lt;/p&gt;
&lt;p&gt;The allocation healing part of this implementation is temporary to support
upgrading existing deployments with PCI allocations to the new Placement based
logic. As soon as a deployment is upgraded and the scheduler logic is enabled
the healing is expect to be noop as the scheduler creates all the necessary
allocation in Placement. Therefore we plan to remove the healing logic from
the codebase in a future release.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The compute restart logic needs to handle the case when a device is not
present any more either due to changes in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; config
option or due to a physical device removal from the hypervisor. The driver
needs to modify the VF resource inventory on the PF RP (when a VF is removed)
or delete the PF RP (if the PF is removed and no children VFs matched). Nova
cannot prevent the removal of a PCI device from the hypervisor while the
device is allocated to a VM. Still Nova will emit a warning in such case.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="pci-alias-configuration"&gt;
&lt;h3&gt;PCI alias configuration&lt;/h3&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#pci.alias"&gt;PCI alias definition&lt;/a&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]alias&lt;/span&gt;&lt;/code&gt; configuration option will be
extended to support two new tags, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt;. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; tag can hold exactly one resource class name. While the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag can hold a comma-separated list of trait names. Also trait names
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; can be prefixed with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;!&lt;/span&gt;&lt;/code&gt; to express a forbidden trait.
When the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; is specified, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt;
tags will no longer be required.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt; fields are
provided in the alias then Nova will use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; for the
Placement query but the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vendor_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_id&lt;/span&gt;&lt;/code&gt; filtering will
happen in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Later if more complex trait requirements are needed we can add support for
multiple &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag by adding a free postfix. Also later we can add
support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in:&lt;/span&gt;&lt;/code&gt; prefix in the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits&lt;/span&gt;&lt;/code&gt; tag to express
an OR relationship. E.g.&lt;/p&gt;
&lt;div class="highlight-js notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"traits1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1,!T2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"traits2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in:T3,T4"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="requesting-pci-devices"&gt;
&lt;h3&gt;Requesting PCI devices&lt;/h3&gt;
&lt;p&gt;The syntax and handling of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough:alias&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/extra-specs.html#pci_passthrough:alias"&gt;flavor extra specs&lt;/a&gt;
will not change. Also, Nova will continue using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; to
track the requested PCI devices for a VM.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="scheduling"&gt;
&lt;h3&gt;Scheduling&lt;/h3&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;The implementation of the scheduling support has missed the deadline and
therefore not part of the Zed release.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; creation logic is extended to translate
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; objects and store the new
groups in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt;. At this time
nova will only translate flavor based InstancePCIRequests the neutron port
based requests will be handled in a later release.&lt;/p&gt;
&lt;p&gt;This translation logic is disable by default and can be enabled via the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[filter_scheduler]pci_in_placement&lt;/span&gt;&lt;/code&gt; configuration after every compute in
the deployment is upgraded and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; configuration
option is enabled.&lt;/p&gt;
&lt;p&gt;To be able to unambiguously connect &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroups&lt;/span&gt;&lt;/code&gt; the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;request_id&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; object
always needs to be filled to a UUID. In the past nova only filled that field
for neutron based requests.&lt;/p&gt;
&lt;p&gt;A single &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; object can potentially request multiple devices
as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;count&lt;/span&gt;&lt;/code&gt; field can be set to greater than 1 for flavor based request.
In this case a single request object is split into multiple &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt;
objects to allow fulfilling those device requests from independent resource
providers. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt; of the resulting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; objects are
filled with a value generated by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest.request_id-&amp;lt;index&amp;gt;&lt;/span&gt;&lt;/code&gt;
formula where index is a runing index between 0..``count`` from the request.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required_traits&lt;/span&gt;&lt;/code&gt; filed of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; object
is filled based on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spec&lt;/span&gt;&lt;/code&gt; field of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; that in
turn are filled from the fields of the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]alias&lt;/span&gt;&lt;/code&gt; entry
requested via the flavor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extras_spec&lt;/span&gt;&lt;/code&gt;. If a request comes from an alias that
does not have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; associated with it, then it will be
defaulted to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PCI_&amp;lt;vendor_id&amp;gt;_&amp;lt;product_id&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The existing scheduler implementation can be used to generate the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/allocation_candidates&lt;/span&gt;&lt;/code&gt; query to Placement including the new PCI related
groups.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependent-device-handling"&gt;
&lt;h3&gt;Dependent device handling&lt;/h3&gt;
&lt;p&gt;Today nova allows matching both a parent PF and its children VFs in the
configuration and these devices are tracked as separate resources. However,
they cannot be consumed independently. When the PF is consumed its children VFs
become unavailable. Also when a VF is consumed its parent PF becomes
unavailable. This dynamic device type selection will be deprecated and the new
Placement based PCI tracking will only allow configuring either the PF device
or its children VF devices. The old PCI tracker will continue support this
functionality but as soon as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt; is set to True on a
compute that compute will reject configurations that are enabling both the PF
and in children VFs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="pci-numa-affinity"&gt;
&lt;h3&gt;PCI NUMA affinity&lt;/h3&gt;
&lt;p&gt;The PCI NUMA affinity code (mostly in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hardware.py&lt;/span&gt;&lt;/code&gt;) will need to be modified
to limit the PCI devices considered to just those included in the allocation
candidate summary. Also at the same time, this code should provide information
to the scheduler about which allocation candidate is valid from affinity
perspective.&lt;/p&gt;
&lt;p&gt;To enable this the allocation candidates will be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt;
object of the filter scheduler. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; will then need to pass the allocation candidates to the
hardware.py functions which will need to remove any allocation candidates from
that list that do not fulfill the PCI or NUMA requirements. The filter should
then pop any invalid allocation candidates from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object. At
the end of the scheduling process, the filter scheduler will have to
reconstruct the host allocation candidate set from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;By extending the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object with the allocation candidate we will
enable the filters to filter not just by the host but optionally by the
allocation candidates of the host without altering the filter API therefore
maintaining compatibility with external filters.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="the-pci-stats-module"&gt;
&lt;h3&gt;The PCI stats module&lt;/h3&gt;
&lt;p&gt;The stats module will have to be enhanced to support allocation aware claims.
To the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDevicePool&lt;/span&gt;&lt;/code&gt; object needs to be mapped to resource providers. This
will be done by the PCI device inventory reporting logic in the PciDevTracker.
During a scheduling attempt the scheduler filters can provide the resource
provider UUIDs that the current allocation candidate is mapped to to restrict
the PCI fitting logic according to the candidate.&lt;/p&gt;
&lt;p&gt;After the scheduling decision is made the selected mapping is recorded into
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects. So that during the PCI claim logic this
information will be provider from those objects to ensure that the claim
consumes PCI devices that are allocated for this request in Placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vm-lifecycle-operations"&gt;
&lt;h3&gt;VM lifecycle operations&lt;/h3&gt;
&lt;p&gt;The initial scheduling is very similar to the later scheduling done due to
move operations. So, the existing implementation can be reused. Also, the
current logic that switches the source node Placement allocation to be held by
the migration UUID can be reused.&lt;/p&gt;
&lt;p&gt;Live migration is not supported with PCI alias-based PCI devices and this will
not be changed by the current spec.&lt;/p&gt;
&lt;p&gt;Attaching and detaching PCI devices are only supported via Neutron SR-IOV ports
and that is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="neutron-sr-iov-ports-out-of-scope"&gt;
&lt;h3&gt;Neutron SR-IOV ports (out of scope)&lt;/h3&gt;
&lt;p&gt;This is out of scope in the current spec. But certain aspects of the problem
are already known and therefore listed here.&lt;/p&gt;
&lt;p&gt;There are a list of Neutron port &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct-physical&lt;/span&gt;&lt;/code&gt;,etc) where the port needs to be backed by VF or PF PCI
devices.&lt;/p&gt;
&lt;p&gt;In the simpler case when a port only requires a PCI device but does
not require any other resources (e.g. bandwidth) then Nova needs to create
Placement request groups for each Neutron port with the already proposed
prefilter. See &lt;a class="reference internal" href="#scheduling"&gt;Scheduling&lt;/a&gt; for more details. In this case, neither the
name of the resource class nor the vendor ID, product ID pair is known at
scheduling time (compared to the PCI alias case) therefore the prefilter does
not know what resource class needs to be requested in the Placement request
group.&lt;/p&gt;
&lt;p&gt;To resolve this, PCI devices that are intended to be used for Neutron-based
SR-IOV should should not use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; tag in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt;. Instead Nova will use standard resource classes to
model these resource.&lt;/p&gt;
&lt;p&gt;Today nova allows consuming type-PCI or type-VF for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt; ports. This
is mostly there due to historical reasons and it should be cleaned up. A
better device categorization is suggested:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A device in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; will be consumable only via PCI alias
if it does not have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag attached.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A device that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag attached will be considered a
network device and it will be modelled as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt; resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A device that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag and also has the capability to
provide VFs will have a trait &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NIC_SRIOV&lt;/span&gt;&lt;/code&gt; but still use the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt; resource class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A device that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag and is a VF will be modelled
as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SRIOV_NET_VF&lt;/span&gt;&lt;/code&gt; resource.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way every Neutron &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; can be mapped to one single resource
class by Nova. The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; -&amp;gt; resource class mapping is
suggested:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;macvtap&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-forwarder&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote-managed&lt;/span&gt;&lt;/code&gt; -&amp;gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SRIOV_NET_VF&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct-physical&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCI_NETDEV&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VDPA_NETDEV&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nova will use these resource classes to report device inventories to
Placement. Then the prefilter can translate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; of the ports to
request the specific resource class during scheduling.&lt;/p&gt;
&lt;p&gt;Another specialty of Neutron-based SR-IOV is that the devices listed in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; always have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;physical_network&lt;/span&gt;&lt;/code&gt; tag.
This information needs to be reported as a trait to the PF RP in Placement.
Also, the port’s requested physnet needs to be included in the Placement
request group by the prefilter.&lt;/p&gt;
&lt;p&gt;There is a more complex case when the Neutron port not only requests a PCI
device but also requests additional resources (e.g. bandwidth) via the port
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; attribute. In this case, Nova already generates Placement
request groups from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; and as in the simple case will
generate a request group from the PCI request. The resource request
of these groups of a neutron port needs to be correlated to ensure that a port
gets the PCI device and the bandwidth from the same physical device. However
today the bandwidth is modeled under the Neutron RP subtree while PCI devices
will be modeled right under the root RP. So the two RPs to allocate from are
not within the same subtree. (Note that Placement always fulfills a named
request group from a single RP but allows correlating such request groups
within the same subtree.) We have multiple options here:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a scheduler filter that removes allocation candidates where these
request groups are fulfilled from different physical devices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report the bandwidth and the PCI device resource on the same RP. This breaks
the clear ownership of a single RP as the bandwidth is reported by the
neutron agent while the PCI device is reported by Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move the two RPs (bandwidth and PCI dev) into the same subtree. This
needs an agreement between Nova and Neutron devs where to move the RPs and
needs an extra reshape to implement the move.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance Placement to allow sharing of resources between RPs within the same
RP tree. By that, we could make the bandwidth RP a sharing RP that shares
resources with the PCI device RP representing the physical device.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Based on the selected solution either:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Neutron requests the specific resource class for the SRIOV
port via the port &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova can include these resources to the request when the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; objects are created based on the requested ports.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We could keep using the legacy tracking with all its good and bad properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could track each PCI device record as a separate RP.
This would result in each VF having its own RP allowing each VF to have
different traits. This is not proposed as it will significantly increase the
possible permutations of allocation candidates per host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could keep supporting the dynamic PF or VF consumption in Placement but
it is deemed more complex than useful. We will keep supporting it via the
legacy code path but the new code path will not support it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could model each PCI device under a NUMA node.
This can be done in the future by moving the RP under a NUMA node RP instead
of the compute node RP but it is declared out of the scope of this initial
spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; object will be extended to include the required and
forbidden traits and the resource class requested via the PCI alias in the
flavor and defined in the PCI alias configuration.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDevicePool&lt;/span&gt;&lt;/code&gt; object will be extended to store a resource provider UUID so
that the PCI device allocated in Placement can be correlated to the PCI device
to be claimed by the PCI tracker.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;In general, this is expected to improve the scheduling performance but
should have no runtime performance impact on guests.&lt;/p&gt;
&lt;p&gt;The introduction of new PCI &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; objects will make the computation
of the placement query slightly longer and the resulting execution time may
increase for instances with PCI requests but should have no effect for
instances without PCI requests. This added complexity is expected to be offset
the result of the offloading of the filtering to Placement and the removal of
reschedules due to racing for the last PCI device on a host, the overall
performance is expected to improve.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;To utilize the new feature the operator will have to define two new config
options. One to enable the placement scheduling logic and a second to enable
the reporting of the PCI devices to Placement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The new Placement based PCI tracking will be disabled by default. Deployments
already using PCI devices can freely upgrade to the new Nova version without
any impact. At this state the PCI device management will be done by the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciPassthroughFilter&lt;/span&gt;&lt;/code&gt; in the scheduler and the PCI claim in the PCI device
tracker in the compute service same as in the previous version of Nova.
Then after the upgrade the new PCI device tracking can be enabled in two
phases.&lt;/p&gt;
&lt;p&gt;First the PCI inventory reporting needs to be enabled by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt;&lt;/code&gt; on each compute host. During the startup of the
nova-compute service with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; config the
service will do the reshape of the provider tree and start reporting PCI device
inventory to Placement. Nova compute will also heal the PCI allocation of the
existing instances in Placement. This healing will be done for new
instances with PCI requests until a future release where the prefilter enabled
by default. This is needed to keep the resource usage in sync in Placement
even if the instance scheduling is done without the prefilter requesting
PCI allocations in Placement.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Operators are encouraged to take the opportunity to rename the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; config option to the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt;
option. The syntax of the two options are the same.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; tag is not supported in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]device_spec&lt;/span&gt;&lt;/code&gt; and in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; any more if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt;&lt;/code&gt; is
enabled. We suggest to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;address&lt;/span&gt;&lt;/code&gt; tag instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If the deployment is configured to rely on the dynamic dependent device
behavior, i.e. both the PF and its children VFs are matching the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; then reconfiguration will be needed as the new code patch
will not support this and the nova-compute service will reject to start with
such configuration. To do the reconfiguration the deployer needs to look at
the current allocation of the PCI devices on each compute node:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;if neither the PF nor any of its children VFs are allocated then the
deployer can decide which device(s) kept in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if the PF is already allocated then the PF needs to be kept in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; but all children VFs has to be removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if any of the children VF device is allocated then the parent PF needs to
be removed from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; and at least the currently allocated
VFs needs to be kept in the config, while other non allocated children VFs
can be kept or removed from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; at will.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Once &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_to_placement&lt;/span&gt;&lt;/code&gt; is enabled for a compute host it cannot be
disabled any more.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Second, after every compute has been configured to report PCI inventories to
Placement the scheduling logic needs to be enabled in the nova-scheduler
configuration via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[filter_scheduler]pci_in_placement&lt;/span&gt;&lt;/code&gt; configuration
option.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;rename PCI &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passthrough_whitelist&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;support for adding a resource class and traits to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]report_in_placement&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;reject dependent devices config and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devname&lt;/span&gt;&lt;/code&gt; config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PCI reshape and allocation healing for existing instances&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;support for adding resource class and required and forbidden traits to PCI
alias&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;prefilter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object with an allocations candidate list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension of scheduler to populate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostState&lt;/span&gt;&lt;/code&gt; object with candidates and
then reconstruct the candidate list after filtering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hardware.py&lt;/span&gt;&lt;/code&gt; to consider allocation candidates when filtering
for NUMA affinity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extension of PCI manager claiming to be allocation aware.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The unified limits feature exists in an opt-in, experimental state and will
allow defining limits for the new PCI resources if enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;As this is a PCI passthrough related feature it cannot be tested in upstream
tempest. Testing will be primarily done via the extensive unit and functional
test suites that exists for instances with PCI devices and NUMA topology in the
libvirt functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The PCI passthrough doc will have to be rewritten to document the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_class&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait&lt;/span&gt;&lt;/code&gt; tags for the PCI &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_spec&lt;/span&gt;&lt;/code&gt; and
PCI alias.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="cpu-resource-tracking-spec"&gt;CPU resource tracking spec&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/cpu-resources.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/cpu-resources.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="unified-limits-integration-in-nova"&gt;Unified Limits Integration in Nova&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/unified-limits-nova.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/unified-limits-nova.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="support-virtual-gpu-resources"&gt;Support virtual GPU resources&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/add-support-for-vgpu.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/add-support-for-vgpu.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Extended and re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 30 Aug 2022 00:00:00 </pubDate></item><item><title>Robustify Compute Node Hostname Handling</title><link>https://specs.openstack.org/openstack/nova-specs/specs/backlog/approved/robustify-compute-hostnames.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova has long had a dependency on an unchanging hostname on the
compute nodes. This spec aims to address this limitation, at least
from the perspective of being able to detect an accidental change and
avoiding catastrophe in the database that can currently result from a
hostname change, whether intentional or not.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently nova uses the hostname of the compute (specifically
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.host&lt;/span&gt;&lt;/code&gt;) for a variety of things:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As the routing key for communicating with a compute node over RPC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As the link between the instance, service and compute node objects
in the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For neutron to bind ports to the proper hostname (and in some
cases, it must match the equivalent setting in the neutron agent
config)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For cinder to export a volume to the proper host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As the resource provider name in placement (this actually comes
from libvirt’s notion of the hostname, not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.host&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the hostname of the compute node changes, all of these links
break. Upon starting the compute node with the changed name, we will
be unable to find a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Service&lt;/span&gt;&lt;/code&gt; record in the
database that matches, and will create a new one. After that, we will
fail to find the matching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode&lt;/span&gt;&lt;/code&gt; record and create a new one
of those, with a new UUID. Instances that refer to both the old
compute and service records will not be associated with the running
host, and thus become unmanageable through the API. Further, new
instances that end up created on the compute node after the rename
will be able to claim resources that have been promised to the
orphaned instances (such as PCI devices and VCPUs) as the tracking of
those is associated with the old compute node record.&lt;/p&gt;
&lt;p&gt;If the orphaned instances are relatively static, the first indication
that something has gone wrong may be long after the actual rename,
where reality has forked and there are instances running on one
compute node that refer to two different compute node records and thus
are accounted for in two separate locations.&lt;/p&gt;
&lt;p&gt;Further, neutron, cinder, and placement resources will have the old
information for existing instances and new information for current
instances, which requires reconciliation. This situation may also
prevent restarting old instances if the old hostname is no longer
reachable.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to make sure my database does not get
corrupted due to a temporary or permanent DNS change or outage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I may need to change the name of a compute node as
my network evolves over many years.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a deployment tool writer, I want to make sure that changes in
tooling and libraries never cause data loss or database corruption.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are multiple things we can do here to robustify Nova’s handling
of this data. Each one increases safety, but we do not have to do all
of them.&lt;/p&gt;
&lt;section id="ensure-a-stable-compute-node-uuid"&gt;
&lt;h3&gt;Ensure a stable compute node UUID&lt;/h3&gt;
&lt;p&gt;For non-ironic virt drivers, whenever we generate a compute node uuid,
we should write that to a file on the local disk. Whenever we start,
we should look for that UUID file, use that, and under no
circumstances should we generate another one. To facilitate
pre-generating this by deployment tools, we should use this if we are
starting for the first time and create a ComputeNode record in the
database.&lt;/p&gt;
&lt;p&gt;We would put the actual lookup of the compute node UUID in the
&lt;cite&gt;get_available_nodes()&lt;/cite&gt; method of the virt driver (or create a new
UUID-specific one). Ironic would override this with its current
implementation that returns UUIDs based on the state of Ironic and the
hash ring. Thus only non-Ironic computes would read and write the
persistent UUID file.&lt;/p&gt;
&lt;p&gt;Single-host virt drivers like libvirt would be able to tolerate a
system hostname change, updating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeNode.hypervisor_hostname&lt;/span&gt;&lt;/code&gt;
without breaking things.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="link-computenode-records-with-service-records-by-id"&gt;
&lt;h3&gt;Link ComputeNode records with Service records by id&lt;/h3&gt;
&lt;p&gt;Currently the ComputeNode and Service records are associated in the
database purely by the hostname string. This means that they can
become disassociated, and is also not ideal from a performance
standpoint. Some other data structures are linked against ComputeNode
by id, and thus are not re-associated when the name matches.&lt;/p&gt;
&lt;p&gt;This relationship used to exist, but was &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/kilo/implemented/detach-service-from-computenode.html"&gt;removed&lt;/a&gt; in the Kilo
timeframe. I believe this was due to the desire to make the process
less focused on the service object and more on the compute node
(potentially because of Ironic) although the breaking of that tight
relationship has serious downsides as well. I think we can keep the
tight binding for single-host computes where it makes sense.&lt;/p&gt;
&lt;p&gt;At startup, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; should resolve its ComputeNode object via
the persistent UUID, find the associated Service, and fail to start if
the hostname does not match CONF.host. Since this is used with
external services, we should not just “fix it” as those other links
will be broken as well. This will at least allow us to avoid opening
the window for silent data corruption.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="link-instances-to-a-computenode-by-id"&gt;
&lt;h3&gt;Link Instances to a ComputeNode by id&lt;/h3&gt;
&lt;p&gt;Currently instance records are linked to their Service and ComputeNode
objects purely by hostname. We should link them to a ComputeNode by
its id. Since we need the Service in order to get the RPC routing key
or for hostname resolution when talking to external services, we
should find that based on the Instance-&amp;gt;ComputeNode-&amp;gt;Service id
relationship.&lt;/p&gt;
&lt;p&gt;We already link PCI allocations for instances to the compute node by
id, even though the instance itself is linked via hostname. This
discrepancy makes it easy to get one out of sync with the other.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="potential-changes-in-the-future"&gt;
&lt;h3&gt;Potential Changes in the future&lt;/h3&gt;
&lt;p&gt;If the above changes are made, we open ourselves to the future
possibility for supporting:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Renaming service objects through the API if a compute host really
needs to have its hostname changed. This will require changes to
the other services at the same time, but nova would at least have a
single source of truth for the hostname, making it feasible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If we do all of this, Nova could potentially be confident enough of
an intentional rename that it could update port bindings, cinder
volume attachments, and placement resources to make it seamless.es&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moving to the use of the service UUID as the RPC routing key, if
desired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dropping quite a bit of duplicate string fields from our database.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We can always do nothing. Compute hostnames have been unchangeable
forever, and the status quo is “don’t do that or it will break” which
is certainly something we could continue to rely on.&lt;/p&gt;
&lt;p&gt;We could implement part of this (i.e. the persistent ComputeNode UUID)
without the rest of the database changes. This would allow us to
detect the situation and abort, but without (the work required to get)
the benefits of a more robust database schema that could potentially
also support voluntary renames.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Most of the impact here is to the data model for Instance,
ComputeNode, Service. Other models that reference compute hostnames
may also make sense to change (although it’s also reasonable to punt
that entirely or to a different phase). Examples:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;InstanceFault&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;InstanceActionEvent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TaskLog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ConsoleAuthToken&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further, host aggregates use the service name for
membership. Migrating those to database IDs is not possible since
multiple cells will cause overlap. We could migrate those to UUIDs or
simply ignore this case and assume that any &lt;em&gt;actual&lt;/em&gt; rename operation
in the future would involve API operations to fix aggregates (which is
doable, unlike changing the host of things like Instance).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;No specific REST API impact for this, other than the potential for
enabling a mutable Service hostname in the future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Not visible to end users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Theoretically some benefit comes from integer-based linkages between
these objects that are currently linked by strings. Eventually we
could reduce a bunch of string duplication from our DB schema and
footprint.&lt;/p&gt;
&lt;p&gt;There will definitely be a one-time performance impact due to the
online data migration(s) required to move to the more robust schema.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;This is really all an (eventual) benefit to the deployer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;There will be some churn in the database models during the
transition. Looking up the hostname of an instance will require
Instance-&amp;gt;ComputeNode-&amp;gt;Service, but this can probably be hidden with
helpers in the Instance object such that not much has to change in the
actual workflow.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;There will be some substantial online data migrations required to get
things into the new schema, and the benefits will only be achievable
in a subsequent release once everything is converted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Persist the compute node UUID to disk when we generate it. Read the
compute node UUID from that location if it exists before we look to
see if we need to generate, create, or find an existing node record.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the compute startup procedures to abort if we detect a
mismatch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the schema changes to link database models by id. The
ComputeNode and Service objects/tables still have the id fields that
we can re-enable without even needing a schema change on those.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the data models honor the ID-based linkages, if present&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write an online data migration to construct those links on existing
databases&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Later, there will be work items to:
* Drop the legacy columns
* Potentially implement an actual service rename procedure&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;There should be no external dependencies for the base of this work,
but there is a dependency on the release cycle, which affects how
quickly we can implement this and drop the old way of doing it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional testing for the actual compute node startup
behavior should be fine. Existing integration testing should ensure
that we haven’t broken any of the runtime behavior. Grenade jobs
will test the data migration and we can implement some nova status
items to help validate things in those upgrade jobs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;There will need to be some documentation about the persistent compute
node UUID file for deployers and tool authors. Ideally, the only
visible result of this would be some additional failure modes if the
compute service detects an unexpected rename, so some documentation of
what that looks like and what to do about it would be helpful.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;TODO(danms): There are probably bugs we can reference about compute
node renames being not possible, or problematic if/when they happen.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 19 Aug 2022 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/2023.1/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;2023.1 Antelope&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 26 Jul 2022 00:00:00 </pubDate></item><item><title>support live migration with virtual persistent memory</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/support-live-migration-with-virtual-persistent-memory.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-live-migration-with-virtual-persistent-memory"&gt;https://blueprints.launchpad.net/nova/+spec/support-live-migration-with-virtual-persistent-memory&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Live migration with virtual persistent memory (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vpmem&lt;/span&gt;&lt;/code&gt; for short) is
supported by QEMU and Libvirt. This spec seeks to enable this support in
OpenStack Nova.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Basic functions for virtual persistent memory are supported in OpenStack Nova
from Train release, including resource tracking and creating/resizing instance
with virtual persistent memory, etc. See &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/train/approved/virtual-persistent-memory.html"&gt;virtual persistent memory spec&lt;/a&gt;.
Pre-copy live migration with virtual persistent memory is supported by QEMU
and Libvirt, post-copy with vpmem is not supported, so this spec seeks to
enable pre-copy live migration with vpmem.&lt;/p&gt;
&lt;p&gt;Currently vpmems are stored in instance.resources as ResourceMetadata object,
or stored in migration_context when migrating. As far as Nova concerned,
several problems need to be addressed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Disable post-copy live migration with vpmem even if post-copy is enabled
by nova configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Claim resources from placement when migrating&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign specific resources to instance according to the allcations from
placement and track them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prepare dest xml on the source host, which is used to launch live migration,
that means we need to bring the resources info claimed on dest host to
source host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;vpmem resources need cleanup correctly after live migration successes/fails&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Administrator needs the virtual persistent memory data migrated correctly
during live migration.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova Conductor:
if we specify parameter ‘host’ and ‘force’ for live migration, current
code will firstly assign specific resources to instance on dest host and
then claim resources from placement, we need reverse the order since we rely
on allocations getting from placement to assign specific resources, which is
also our proposed change in following Nova compute.
Before live migration starts, we need check and reject vpmem live migration
if the source host or dest host doesn’t support live migration with vpmem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova Compute:
use resource tracker to assign and track specific resources on
the dest host according to the allocations from placement, and stored in
instance.migration_context (reuse the code introduced by vpmem resize
implementation)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt Driver change for vpmem post-copy disable:
if the instance has vpmems, disable the post-copy live migration even if
post-copy is enabled by Nova configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt Driver change for vpmem xml:
prepare dest xml on source host for live migration, update the dest virtual
persistent memory info into dest xml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt Driver change for vpmem cleanup:
If live migration fails, rollback_live_migration_at_destination will cleanup
vpmems from instance.resources, but instance.resources is still pointing at
the resources on source host. There are other similar cleanup issues.
We can pass one more parameter to driver.cleanup to tell this cleanup is on
source/dest host. Alternatively, we can use the mutated_migration_context
to switch instance.resources to new resources on dest host temporarily. It’s
implementation detail which should be determined when coding.
In a word, we should be careful about vpmem cleanup, especially during
migration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;We are using the existing instance.migration_context bring the dest vpmems info
to source host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;In virtualization layer, QEMU will copy vpmem over the network like volatile
memory. But due to the typical large capacity of vpmem, it may takes longer
time for live migration. If the instance workloads was actively writing to
the vpmem, the live migration might never complete which goes for standard
memory as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Both source and dest host needs upgrade, then live migration with vpmem will
be supported, otherwise it will be rejected.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;luyaozhong&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;xuhj
rui-zang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;luyaozhong&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;implement virtual persistent memory live migration management in Nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get 3rd party CI tests ready&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Kernel version &amp;gt;= 4.2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU version &amp;gt;= 3.1.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt version &amp;gt;= 5.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ndctl version &amp;gt;= 62&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;daxio version &amp;gt;= 1.4.1&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;unittests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Third party CI is required for testing on real hardware. For existing virtual
persistent memory feature in Nova, there are 2 tempest tests, creating and
same host resizing running in the 3rd party CI. Besides, multinode cold
migration, live migration, and shelve/unshelve tests are required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update virtual persistent memory document in Nova “advanced configuration” to
notify administrator that live migration with virtual persistent memory is
supported in Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 12 May 2022 00:00:00 </pubDate></item><item><title>&lt;cite&gt;socket&lt;/cite&gt; PCI NUMA affinity Policy</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/pci-socket-affinity.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pci-socket-affinity"&gt;https://blueprints.launchpad.net/nova/+spec/pci-socket-affinity&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova’s current support for NUMA affinity for PCI devices is limited in the
kinds of affinity that it can express. Either a PCI device has affinity for a
NUMA node, or no affinity at all. This makes one of two assumptions about the
underlying host NUMA topology. Either there is only a single NUMA node per
socket, or - for cluster on die topologies with multiple nodes per socket -
there are enough CPUs in each NUMA node to fit reasonably large VMs that
require strict PCI NUMA affinity. The latter assumption is no longer true, and
Nova needs a more nuanced way to express PCI NUMA affinity.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Consider a guest with 16 CPUs and a PCI device, and a &lt;cite&gt;require&lt;/cite&gt; PCI
NUMA affinity policy. Such a policy requires the guest to “fit” entirely into
the host NUMA node to which the PCI device is affined. Until recently, this was
a reasonnable expectation: more than 16 CPUs per NUMA node was the norm, even
in hosts with multiple NUMA nodes per socket.&lt;/p&gt;
&lt;p&gt;With more recent hardware like AMD’s Zen2 architecture, this is no longer the
case. Depending on the BIOS configuration, there could be as little as 8 CPUs
per NUMA node. This effectively makes a 16-CPU guest with a &lt;cite&gt;require&lt;/cite&gt; PCI
device un-schedulable, as no host NUMA node can fit the entire guest.&lt;/p&gt;
&lt;div class="admonition seealso"&gt;
&lt;p class="admonition-title"&gt;See also&lt;/p&gt;
&lt;p&gt;Zen2 BIOSes have a L3AsNUMA configuration option, which creates a
NUMA node for every level 3 cache. Up to 4 cores can share an L3 cache, with
2 SMT threads per core. This is how the number 8 was arrived at. See the AMD
Developer Documentation &lt;a class="footnote-reference brackets" href="#id2" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an NFV cloud operator, I want to make full use of my hardware (AMD Zen2, or
Intel with cluster on die enabled) with minimal performance penalties.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes a new value for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; (and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; image property). The value is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt;, and
it indicates that the instance’s PCI device has to be affined to the same
socket as the host CPUs that it is pinned to. If no such devices are available
on any compute hosts, the instance fails to schedule. In that sense, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt;
is the same as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;require&lt;/span&gt;&lt;/code&gt;, except the PCI device must belong to the same
socket, rather than the same host NUMA node. In the case of multiple NUMA
nodes, the PCI device must belong to the same socket as &lt;em&gt;one&lt;/em&gt; of the NUMA
nodes.&lt;/p&gt;
&lt;p&gt;To better understand the new policy, consider some examples.&lt;/p&gt;
&lt;p&gt;In the following oversimplified diagram, an instance with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_numa_nodes=1&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy=socket&lt;/span&gt;&lt;/code&gt; can be pinned to NUMA node N0 or N1,
but not N2 or N3&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+----------+&lt;/span&gt;         &lt;span class="o"&gt;+----------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N0&lt;/span&gt;    &lt;span class="n"&gt;N1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;N2&lt;/span&gt;    &lt;span class="n"&gt;N3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;+---&lt;/span&gt;&lt;span class="n"&gt;PCI&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Socket&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Socket&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------+&lt;/span&gt;         &lt;span class="o"&gt;+----------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Remaining with the same diagram, if the instance has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_numa_nodes=2&lt;/span&gt;&lt;/code&gt;
instead, it can be pinned to the following, as they all have at least one guest
NUMA node pinned to the PCI device’s socket.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;N0 and N1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N0 and N2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N0 and N3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N1 and N2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N1 and N3&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The instance cannot be pinned to N2 and N3, as they’re both on a different
socket from the PCI device.&lt;/p&gt;
&lt;p&gt;The implementation requires knowing the socket affinity of host CPUs and PCI
devices. For CPUs, the libvirt driver obtains that information from libvirt’s
host capabilities and saves it in a new field in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMACell&lt;/span&gt;&lt;/code&gt; object. For
PCI devices, the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCIDevice.numa_node&lt;/span&gt;&lt;/code&gt; field can be used to look up
the corresponding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMACell&lt;/span&gt;&lt;/code&gt; object and obtain its socket affinity.&lt;/p&gt;
&lt;p&gt;The socket affinity information is then used in
hardware.py’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;numa_fit_instance_to_host()&lt;/span&gt;&lt;/code&gt;, specifically when it calls down
to the PCI manager’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;support_requests()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There are no alternatives with a similar level of simplicity. A more complex
model could include numeric NUMA distances and/or PCI root complex electrical
connection vs memory mapping affinity.&lt;/p&gt;
&lt;p&gt;At the implementation level, an alternative to looking up the PCI device socket
affinity every time is to save it in a new field in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCIDevice&lt;/span&gt;&lt;/code&gt; object.
This is ruled out because it adds a database migration, and is less flexible
and future-proof.&lt;/p&gt;
&lt;p&gt;Another alternative for the same purpose is to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info&lt;/span&gt;&lt;/code&gt; field in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCIDevice&lt;/span&gt;&lt;/code&gt;. It is a JSON blob that can accept arbitrary new entries. One of
the original purposes of Nova objects was to avoid unversioned dicts flying
over the wire. Relying on JSON blobs inside objects goes against this. In
addition, socket affinity is applicable to all PCI devices, and so does not
belong in a device-specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; integer field is added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMACell&lt;/span&gt;&lt;/code&gt; object. No database
changes are necessary here, as the object is stored as a JSON blob. The field
is populated at runtime by the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;No API changes per se, and definitely no new microversion. A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt;
value is added to the list of possible values for the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; flavor extra spec and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; image property. The flavor extra spec
validation logic is extended to support the new value.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There is minimal impact on Nova performance. Documentation on the performance
impact of using the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; NUMA affinity policy on various
architectures may be necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Only the libvirt driver supports PCI NUMA affinity policies. This spec builds
on that support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The current (pre-Wallaby) implementation of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_filter_pools_for_numa_cells()&lt;/span&gt;&lt;/code&gt;
recognizes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;preferred&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;legacy&lt;/span&gt;&lt;/code&gt; as values for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt;, with the latter being the catch-all default.
Therefore, instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy=socket&lt;/span&gt;&lt;/code&gt; cannot be
permitted to land on pre-Wallaby compute hosts: the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; value would not
be recognized, and they would be incorrectly treated as having the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;legacy&lt;/span&gt;&lt;/code&gt; value.&lt;/p&gt;
&lt;p&gt;To ensure that only Wallaby compute hosts receive instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy=socket&lt;/span&gt;&lt;/code&gt;, a new trait is reported by the Wallaby
libvirt driver to indicate that it supports the new policy. A corresponding
request pre-filter is added.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;notartom&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; integer field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMACell&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt driver starts populating the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMACell.socket&lt;/span&gt;&lt;/code&gt; field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDeviceStats._filter_pools()&lt;/span&gt;&lt;/code&gt;, as called by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDeviceStats.support_requests()&lt;/span&gt;&lt;/code&gt;, to support the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt;
NUMA affinity policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add COMPUTE_SOCKET_NUMA_AFFINITY trait (name can be adjusted during
implementation) and corresponding pre-filter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend the flavor extra spec validation to allow the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; value.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;While there are aspirations for AMD Zen2 hardware in a third party CI, that is
too far in the future to have any impact on this spec. Functional tests will
have to do.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The behavior of the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; NUMA affinity policy will be documented.
Documentation on the performance impact of using the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socket&lt;/span&gt;&lt;/code&gt; NUMA
affinity policy on various architectures may be necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://developer.amd.com/wp-content/resources/56338_1.00_pub.pdf"&gt;Socket SP3 Platform NUMA TopologyforAMD Family 17h
Models30h–3Fh&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 12 May 2022 00:00:00 </pubDate></item><item><title>Allow Project admin to list allowed hypervisors</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/allow-project-admin-list-hypervisors.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/allow-project-admin-list-hypervisors"&gt;https://blueprints.launchpad.net/nova/+spec/allow-project-admin-list-hypervisors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow Project admin to get the allowed hypervisors info so that
they can create a server to specify the host in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Project admin can currently create a server on a specific hypervisor (via host
in the availability_zone field). However, project admin is not allowed to
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/policies/hypervisors.py#L37"&gt;list the hypervisors&lt;/a&gt; On the other hand, only system admins or system
readers can list hypervisors, but they cannot create a server on the project’s
behalf because there is no way to pass the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/api/openstack/compute/schemas/servers.py#L149"&gt;project_id in POST /servers API&lt;/a&gt;.
This way, we make ‘POST /servers with specific host’ unusable unless the user
gives extra token permission to the project admin or system users.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user (project admin currently and project manager in new RBAC), I should
be able to create the server on specific host which is assigned in that
project.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Below are the three proposed changes:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-hypervisors&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;
&lt;p&gt;Allow project admin to list &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;state&lt;/span&gt;&lt;/code&gt;, and, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt;
of the hypervisors they are assigned to. That will be retrieved from
aggregate metadata info (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_tenant_id&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If the requested project is in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_tenant_id&lt;/span&gt;&lt;/code&gt; then that host info will
be listed for project admin. If no project is listed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_tenant_id&lt;/span&gt;&lt;/code&gt;
then return an empty list. Only below hypervisors’ fields will be returned
for project admin, and the rest of the fields will be returned with value
as None.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;uuid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;status&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No change in returning the hypervisors list for System scoped users.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API will start accepting hypervisor uuid in request field
to boot the server on that hypervisor. The existing field
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; is used to pass the hypervisor name and we will not
change that for existing use case. We will add a new field
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_uuid&lt;/span&gt;&lt;/code&gt; in request so that user can pass hypervisor uuid. The
hypervisor uuid will be used to boot the server for for host with scheduler
run case.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the legacy hack of passing the host and node in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt;
request field. This will be removed for newer microversion only and keep it
same for older microversion.&lt;/p&gt;
&lt;p&gt;This is legacy hack to force the server boot on requested host and node.
This one - &lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561&lt;/a&gt;
Removing this legacy hack will standaradize the ‘server boot on requested
host’ request.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;System users knowing the hypervisor info can switch to the project admin token
and boot server on specific host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This change will be done with a microversion bump.&lt;/p&gt;
&lt;p&gt;Below are the two APIs that will be changed:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-hypervisors&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Allow policy ‘os_compute_api:os-hypervisors:list’ to project admin also
(scope to system and project).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the requester is system user or project admin (via request context’s
system_scope). For system users no change in API from what we have currently.
For project admin, return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;state&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; of
those hosts which are assigned to that project, and the rest of the fields
will be returned with value as None.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"hypervisors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"hypervisor_hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1bb62a04-c576-402c-8147-9e89757a09e3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"enabled"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"hypervisors_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API will start accepting hypervisor uuid in request field
to boot the server on that hypervisor. We will add a new  field
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_uuid&lt;/span&gt;&lt;/code&gt; in create server request so that user can pass uuid.
The hypervisor uuid will be used to boot the server for host with scheduler
run case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the legacy hack of passing the host and node in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt;
request field. For older microversions, it will keep working as it is working
currently. With this new microversion, only a valid AZ will be accepted in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt; field otherwise 404. Basically removing this legacy
hack - &lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None. Already assigned host uuid name will be listed to project admin also.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The nova api-ref will updated to reflect the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Upgrade notes will be added for the new workflow of boot server on
specific host.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API changes with microversion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing for the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit or functional testing for API change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest test to boot server with hypervisor uuid.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The api-ref will be updated to reflect the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-xena-ptg"&gt;https://etherpad.opendev.org/p/nova-xena-ptg&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/779821"&gt;https://review.opendev.org/c/openstack/nova-specs/+/779821&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/policies/servers.py#L179"&gt;https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/policies/servers.py#L179&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 04 May 2022 00:00:00 </pubDate></item><item><title>Usage of new OWNER_NOVA trait</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/owner-nova-trait-usage.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/owner-nova-trait-usage"&gt;https://blueprints.launchpad.net/nova/+spec/owner-nova-trait-usage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec is about the usage of new OWNER_NOVA trait.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Today in placement each resource class is typically only used by a single
service. With the introduction of VGPU support in cyborg both nova and cyborg
now share ownership or usage of the VGPU resource class. This creates a usage
problem where different workflows are required to correctly consume the VGPU
resource class based on which service created the inventory.&lt;/p&gt;
&lt;p&gt;As both the nova and cyborg projects can report VGPU resources, we should be
able to solve the shared VGPU resource class problem by each service recording
that they created or “own” the resource provider, however, that is not done
today.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I would like to be able to deploy multiple services that can
share the same resource class name without creating scheduling conflicts.&lt;/p&gt;
&lt;p&gt;As an operator, I want to have a way to transition management of resources
between OpenStack service using simple operations such as resizing an instance
from a flavor that consumes VGPUs provided by nova to a flavor that uses VGPUs
provided by cyborg.&lt;/p&gt;
&lt;p&gt;As an end-user, I would like to be able to consume resources from nova and
cyborg in a single instance without having to understand the detail of
placement or scheduling.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes adding a new OWNER_NOVA trait and pre-filter.
Nova will tag every ResourceProvider it creates with a OWNER_NOVA trait,
implying that inventories are provided by this service only.
Nova will provide a pre-filter that actively requests its own OWNER_NOVA trait
while cyborg will require the OWNER_CYBORG trait via its device profile to
filter their own managed resources.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;That operators will see new traits for all the Resource Providers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;We need to make sure that the nova VGPU feature still works during a rolling
upgrade to the nova version introducing the OWNER_NOVA trait.
So to ensure that the nova compute service version will be bumped to signal
when a compute service is upgraded and therefore reports the OWNER_NOVA trait
on its RPs. The pre-filter filtering on OWNER_NOVA will only be enabled if the
minimum compute service version indicates that every compute service is now
upgraded and therefore reporting the OWNER_NOVA trait.
This way during a rolling upgrade with old compute still present the
pre-filter will not be enabled and the nova VGPU feature will work as today.
But as soon as all the computes are upgraded the pre-filter will automatically
start enforcing the OWNER_NOVA trait for all the nova VGPU feature requests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wenpingsong&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wenpingsong&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add OWNER_NOVA for os_traits project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag every ResourceProvider that nova creates with a OWNER_NOVA trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add pre-filter the trait for every Nova request group.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related unit and functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Need relate unit and functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Modify the related docs with OWNER_NOVA traits for update available resources
and pre-filter scheduler.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 25 Apr 2022 00:00:00 </pubDate></item><item><title>Remove tenant_id</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/remove-tenant-id.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-tenant-id"&gt;https://blueprints.launchpad.net/nova/+spec/remove-tenant-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The blueprint proposes to remove the API interface that uses
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and replace it with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Nova API supports both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;,
which is unfriendly to users.&lt;/p&gt;
&lt;p&gt;The following is a confusing question.
By default, we support filtering instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt; &lt;span class="pre"&gt;(Optional)&lt;/span&gt;&lt;/code&gt;,
but through this parameter, we get a list of all instances that they
cannot get instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can see from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1185290"&gt;bug 1185290&lt;/a&gt; that when using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt; command,
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; is required, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; must appear, as description
in &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, which is somewhat unintuitive.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;a class="footnote-reference brackets" href="#id3" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; mainly said: “As explained in lp:#1185290, if &lt;cite&gt;all_tenants&lt;/cite&gt;
is not passed we must ignore the &lt;cite&gt;tenant_id&lt;/cite&gt; search option.”.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can know from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1468992"&gt;bug 1468992&lt;/a&gt; that many users want to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;
filtering instances, and using the concept of tenants in many of our
large-scale customer scenarios, they hope we can filter the expected
instances through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an (admin) user, I would like to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; uniformly in nova api,
instead of supporting both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;, this will imporve
uniformity within nova and between nova and other service which have already
made this change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to the request or response parameter changes API.&lt;/p&gt;
&lt;p&gt;Remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; field, using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt;
parameter, and then remove``all_tenants`` parameter in the following APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The keyword &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; in the path will be replaced with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; as below
APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage/{tenant_id}&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage/{project_id}&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We should block change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; below the deprecated APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups (List Security Groups)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups/{security_group_id} (Show Security Group Details)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-security-groups/{security_group_id} (Update Security Group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /os-security-group-rules (Create Security Group Rule)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-fping?all_tenants=1 (Ping Instances)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, tenant* reference will be replaced with project* in all policies,
code and docs too.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a new microversion.&lt;/p&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; parameter, and remove
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Update openstacksdk, python-novaclient and python-openstackclient
for the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang, songwenping&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the python-novaclient , python-openstackclient and openstacksdk,
just support requesting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in related APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test for negative scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test (API samples).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary for this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the API reference for the new microversion, and update all uses of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; in all docs and code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Mainly info: &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295"&gt;https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 14 Apr 2022 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store a symmetric key in the key manager. This
remains a long running piece of technical debt in the encrypted volume
implementation as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; does not directly encrypt data with the provided
key.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID.&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypt these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/ephemeral-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/ephemeral-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 31 Mar 2022 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will only cover the high level changes to the API and compute
layers, implementation within specific virt drivers is left for separate
specs.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility traits was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 30 Mar 2022 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will only cover the high level changes to the API and compute
layers, implementation within specific virt drivers is left for separate
specs.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility traits was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>soft-delete instance actions</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/soft-delete-instance-actions.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/soft-delete-instance-actions"&gt;https://blueprints.launchpad.net/nova/+spec/soft-delete-instance-actions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec is mainly a reminder of actions that have to be taken to implement
the soft-delete of instance actions table when an instance is soft-deleted&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently when an instance is soft-deleted the related instance actions are not
soft-deleted to allow the operator to get the history of actions taken on the
instance, especially who soft-deleted the instance.&lt;/p&gt;
&lt;p&gt;This is not an issue as such but we are inconsistent on database level because
instance is marked as deleted but not the actions. We would like to improve
the consitency.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I still want to be able to retrieve instance actions of a soft
deleted instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the instance actions to be soft-deleted when an
instance is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Change how the instance action are fetched&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We must change the database queries that fetch instance action to read soft
deleted instance actions too.&lt;/p&gt;
&lt;p&gt;By doing that we will be able to get instance actions of a soft-deletd instance
before and after this spec is implemented.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Change on instance soft-deleting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When we soft-delete an instance we have to soft-delete all the instance actions
tables (instance_actions, instance_actions_events) referencing the soft-deleted
instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Change on instance restore&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When restoring an instance we have to restore instance_actions and
instance_actions_events too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Impacts on nova-manage&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;nova-manage db archive_deleted_rows&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is no impact on archiving because the filter on deleted column is applyed
on instances table only. Data on children tables are selected according to the
selected instances.
It means that in shadow tables instance actions are not soft deleted, data are
basically moved from main table to shadow table.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;nova-manage db purge&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When using the purge command with the –before flag the filter is applied on
deleted_at column for all tables except instance_actions and
instance_actions_events for which the filter is applied on updated_at column.&lt;/p&gt;
&lt;p&gt;So we have to modify the purge behavior to filter on deleted_at and updated_at
columns for instance_actions and instance_actions_events tables.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The proposed changes works without changing existing data, it means that we are
able to implement soft delete of instance action and make it works with the
already instance actions not soft deleted without changing the API.&lt;/p&gt;
&lt;p&gt;We could add a command to nova-manage db that will update the existing instance
action that should be soft deleted. This implies an upgrade step which is much
more tricky than the proposed change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;instance_actions and instance_actions_events are already implementing the
soft-delete feature so there is no need to change schema.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;The API will continue to return both soft-deleted and not deleted actions.
As the deleted state is not returned in the api response it won’t impact the
API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None as long as we do not choose the alternative.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;pslestang&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Modify the fetch on instance_actions instance_actions_events to read deleted
rows too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;soft delete instance_actions and instance_actions_events when soft deleting
instances&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;purge with –before on instance_actions and instance_actions_events should be
done on deleted_at column too.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Can be tested with unit and functional tests.
We should also verify if API sample tests need to be modified since this should
not have any visible api change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>Boot a VM with an unaddressed port</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/boot-vm-with-unaddressed-port.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/boot-vm-with-unaddressed-port"&gt;https://blueprints.launchpad.net/nova/+spec/boot-vm-with-unaddressed-port&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint aims to allow a VM to boot with an attached port without any IP
assigned.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Neutron permits users to create a port assigned to a network with
corresponding subnets and IP pools, without an IP address assigned. However
Nova only allows users to create a VM with a port without an IP only if this
address assignment is deferred; that means that the port is expected to have
an IP address but Neutron deferred the IP allocation until the host to which
the port will be bound is populated.&lt;/p&gt;
&lt;p&gt;However, there are some network applications (e.g.: service function
forwarding, service function classifier, CMTS) that often forward traffic that
is not intended for them. Those applications have an interface without a
primary L3 address which may be receiving traffic for so many disparate
addresses that configuring all of them in Neutron is a burden.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;A typical use case is when a user wishes to deploy a VM which accepts traffic
that is neither IPv4 nor IPv6 in nature. For example, a CMTS (Cable Modem
Termination System).&lt;/p&gt;
&lt;p&gt;Another use case could be a VM that accepts traffic for a very wide address
range (for either forwarding or termination) and where the port has no primary
address. In such cases, the VM is not a conventional application VM.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to allow to spawn a VM with a manually created port without
IP address assignation.&lt;/p&gt;
&lt;p&gt;When a port in Neutron is created with the option “–no-fixed-ip”, the port
parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; will be populated with “none” &lt;a class="footnote-reference brackets" href="#id9" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This way
Neutron marks a port not to have an IP address. Nova, during the instance
creation, validates the build options; in particular the ports provided to be
bound to this new VM. To be able to use an unaddressed port, Nova needs to
modify the logic where IP assignation is tested &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;As commented in the use cases, some applications will accept traffic that is
neither IPv4 nor IPv6. Having an IP address is irrelevant on those ports but
doesn’t affect the application.&lt;/p&gt;
&lt;p&gt;In other cases, like in a routing application, there is no alternative. It’s
not possible to define in Neutron all the possible IP addresses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;The Neutron port contains the information needed in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt;
parameter and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;connectivity&lt;/span&gt;&lt;/code&gt; parameter inside the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:vif_details&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Those ports without an assigned IP don’t work with the Neutron in-tree
firewalls (iptables and OVS Open Flows based). Both firewalls will filter the
egress and the ingress traffic depending on several parameters, including the
IP address. To let the traffic come into the virtual interface, the firewall
should be disabled in the compute node hosting the VM. This mandatory
configuration will be documented.&lt;/p&gt;
&lt;p&gt;Once the Nova feature is implemented and tested, a new feature will be
requested to Neutron, in order to allow those ports without an IP address to
work correctly with the in-tree firewalls.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;To be able to remotely access to the created VM, the user needs to add an
addressed port to the VM. This “management” port must have an IP address.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Some L2 driver, like “l2-pop”, may have problems when dealing with this kind of
port because they use proxy ARP to answer ARP requests from known IP address.&lt;/p&gt;
&lt;p&gt;The [“novnc”] service won’t work with a port without an IP address. This is why
it’s recommended to create a VM with at least one management port, with an
assigned IP address.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sbauza&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Rodolfo Alonso &amp;lt;rodolfo-alonso-hernandez&amp;gt; (&lt;a class="reference external" href="mailto:ralonsoh%40redhat.com"&gt;ralonsoh&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Change the logic of how the IP assignation is tested &lt;a class="footnote-reference brackets" href="#id10" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the tempest test described.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new Neutron feature request to change the in-tree firewalls to work
correctly with those ports without IP address assigned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None. The necessary work in neutron has already been accomplished via two
specs. The main neutron change was allowing for the creation of an unaddressed
port and mark it, by populating the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt; parameter with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt;.
This was covered by the “Allow vm to boot without l3 address(subnet)” &lt;a class="footnote-reference brackets" href="#id12" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec. The changes introduced as part of the “Port binding event extended
information for Nova” &lt;a class="footnote-reference brackets" href="#id11" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec means neutron will now provide the type of
back-end to which the port is bound, with the parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;connectivity&lt;/span&gt;&lt;/code&gt;,
included now in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:vif_details&lt;/span&gt;&lt;/code&gt;. Nova can determine whether a given
driver back-end has “l2” connectivity and, if so, know that a port without an
IP address can be assigned to a virtual machine.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Apart from the needed functional and unit testing, a tempest test could cover
this feature. This tempest test will spawn three VMs, each one with a
management port, to be able to SSH to the machine. Then two traffic networks
will be created, net1 and net2.&lt;/p&gt;
&lt;p&gt;The first machine will have a port, with an IP assigned, connected to net1.
The third machine will have a port, with an IP assigned, connected to net2.
And finally, the second machine, in the middle of the first and the third one,
with be connected to net1 and net2 with two ports without an IP address.
The second machine will have the needed iptables rules to NAT the traffic
between the first VM and the third VM port.&lt;/p&gt;
&lt;p&gt;Both the first and the third machine will need a manual entry in the ARP table
to force the traffic going out trough the traffic port.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make a reference of this feature in the user document “Launch instances”
&lt;a class="footnote-reference brackets" href="#id13" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/blob/stable/rocky/releasenotes/notes/add-port-ip-allocation-attr-294a580641998240.yaml"&gt;https://github.com/openstack/neutron/blob/stable/rocky/releasenotes/notes/add-port-ip-allocation-attr-294a580641998240.yaml&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/blob/stable/rocky/neutron/db/db_base_plugin_v2.py#L1323"&gt;https://github.com/openstack/neutron/blob/stable/rocky/neutron/db/db_base_plugin_v2.py#L1323&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/stable/rocky/nova/network/neutronv2/api.py#L2078-L2086"&gt;https://github.com/openstack/nova/blob/stable/rocky/nova/network/neutronv2/api.py#L2078-L2086&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/645173/"&gt;https://review.opendev.org/#/c/645173/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/neutron/+spec/vm-without-l3-address"&gt;https://blueprints.launchpad.net/neutron/+spec/vm-without-l3-address&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/stable/rocky/doc/source/user/launch-instances.rst"&gt;https://github.com/openstack/nova/blob/stable/rocky/doc/source/user/launch-instances.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id14"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>Integration With Off-path Network Backends</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/integration-with-off-path-network-backends.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/integration-with-off-path-network-backends"&gt;https://blueprints.launchpad.net/nova/+spec/integration-with-off-path-network-backends&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Off-path SmartNIC DPUs introduce an architecture change where
network agents responsible for NIC switch configuration and representor
interface plugging run on a separate SoC with its own CPU, memory and that runs
a separate OS kernel. The side-effect of that is that hypervisor hostnames no
longer match SmartNIC DPU hostnames which are seen by ovs-vswitchd and OVN &lt;a class="footnote-reference brackets" href="#id42" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
agents while the existing port binding code relies on that. The goal of this
specification is to introduce changes necessary to extend the existing hardware
offload code to cope with the hostname mismatch and related design challenges
while reusing the rest of the code. To do that, PCI(e) add-in card tracking is
introduced for boards with unique serial numbers so that it can be used to
determine the correct hostname of a SmartNIC DPU which is responsible for a
particular VF. Additionally, more information is suggested to be passed in the
“binding:profile” during a port update to facilitate representor port plugging.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="terminology"&gt;
&lt;h3&gt;Terminology&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Data Processing Unit (DPU) - an embedded system that includes a CPU, a NIC
and possibly other components on its board which integrates with the main
board using some I/O interconnect (e.g. PCIe);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Off-path SmartNIC DPU architecture &lt;a class="footnote-reference brackets" href="#id40" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id41" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; - an architecture where NIC
cores are responsible for programming a NIC Switch and are bypassed when
rules programmed into the NIC Switch are enough to make a decision on where
to deliver packets. Normally, NIC cores only participate in packet forwarding
for the “slow path” only and the “fast path” is handled in hardware like an
ASIC;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On-path SmartNIC DPU architecture &lt;a class="footnote-reference brackets" href="#id40" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id41" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; - an architecture where NIC cores
participate in processing of every packet going through the NIC as a whole.
In other words, NIC cores are always on the “fast path” of all packets;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC Switch (or eSwitch) - a programmable embedded switch present in various
types of NICs (SR-IOV-capable NICs, off-path SmartNICs). Typically relies
on ASICs for packet processing;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;switchdev &lt;a class="footnote-reference brackets" href="#id43" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; - in-kernel driver model for switch devices which offload the
forwarding (data) plane from the kernel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Representor ports &lt;a class="footnote-reference brackets" href="#id44" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; - a concept introduced in the switchdev model which
models netdevs representing switch ports. This applies to NIC switch ports
(which can be physical uplink ports, PFs or VFs);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;devlink &lt;a class="footnote-reference brackets" href="#id45" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; - a kernel API to expose device information and resources not
directly related to any device class, such as chip-wide/switch-ASIC-wide
configuration;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PCI/PCIe Vital Product Data (VPD) - a standard capability exposed by PCI(e)
endpoints which, among other information, includes a unique serial number
(read-only, persistent, factory-generated) of a card shared by all functions
exposed by it. Present in PCI local bus 2.1+ and PCIe 4.0+ specifications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="detailed-overview"&gt;
&lt;h3&gt;Detailed overview&lt;/h3&gt;
&lt;p&gt;Cross-project changes have been made over time to support SR-IOV VF allocation
and VF allocation in the context of supporting OVS hardware offload &lt;a class="footnote-reference brackets" href="#id46" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; with
switchdev-capable NICs. However, further work is needed in order to support
off-path SmartNIC DPUs which also expose PCI(e) functions to the hypervisor
hosts.&lt;/p&gt;
&lt;p&gt;When working with ports of type “direct”, instance creation involves several
key steps, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Creating the necessary context based on a client request (including PCI
device requests, e.g. based on “direct” ports associated with an instance
creation request or extra specs of a flavor);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selecting the right host for the instance to be scheduled;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;In the switchdev-capable NIC case: based on availability of devices with
the “switchdev” capability of PciDevices recorded in the Nova DB;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building and running the instance, which involves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Claiming PCI resources via the ResourceTracker at the target host based on
InstancePCIRequests created beforehand;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building other resource requests and updating Neutron port information,
specifically:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;binding_host_id with the hypervisor hostname;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;binding:profile details with PCI device information,
namely: pci_vendor_info, pci_slot, physical_network;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network device assignment for the newly created instance and vif plugging&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;in the switchdev-capable NIC case this involves plugging a VF representor
port into the right OVS bridge;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;programming the necessary flows into the NIC Switch.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rest of the description will focus on illustrating why this process needs
improvements to support off-path SmartNIC DPUs.&lt;/p&gt;
&lt;p&gt;Off-path SmartNIC DPUs provide a dedicated CPU for NIC Switch programming on
which a dedicated OS is set to run which is separate from the OS running on the
main board. A system with one SmartNIC in a multi-CPU system with PCIe
bifurcation used for the add-in card is shown below:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                       ┌──────────────────────────────┐
                       │  Main host (hypervisor)      │
                       │    ┌──────┐      ┌──────┐    │
                       │    │ CPU1 │      │ CPU2 │    │
                       │    │ RC1  │      │ RC2  │    │
                       │    └───┬──┘      └───┬──┘    │
                       │        │             │       │
                       └────────┼─────────────┼───────┘
                                │             │
                                │             │
                            ┌───┴────┐    ┌───┴────┐
          IO interconnect 1 │PF NUMA1│    │PF NUMA2│ IO interconnect 2
               (PCIe)       │VFs     │    │VFs     │    (PCIe)
                            └────┬───┘    └───┬────┘
                                 │            │
┌────────────────────────────────┼────────────┼──────────────────────┐
│SmartNIC DPU Board          ▲   │            │    ▲                 │
│                            │   │            │    │  Fast path      │
│      ┌─────────────┐         ┌─┴────────────┴─┐                    │
│      │ Application │e.g. PCIe│   NIC Switch   │     ┌────────────┐ │
│      │    CPU      ├─────────┤      ASIC      ├─────┤uplink ports│ │
│      │    RC3      │         ├────────────────┤     └────────────┘ │
│ ┌────┴──────┬──────┘   ◄──── │ Management CPU │                    │
│ │OOB Port   │       Slow path│    Firmware    │                    │
│ └───────────┘                └────────────────┘                    │
│                                                                    │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With off-path SmartNIC DPUs, if a NIC Switch has the necessary flows
programmed and an incoming packet matches those flows, it is delivered to the
destination over the fast path bypassing the “Application CPU”. Otherwise, the
packet is processed in software at the Application CPU and then forwarded to
the destination.&lt;/p&gt;
&lt;p&gt;There are more sophisticated scenarios as well:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Two or more SmartNIC DPUs per server attached to different NUMA nodes;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A blade system with managed PCIe switches providing SR-IOV function sharing
of PFs/VFs of the same add-in-card to different compute servers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MR-SR-IOV/PCIe Shared IO &lt;a class="footnote-reference brackets" href="#id47" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Networking agents (e.g. ovs-vswitchd and ovn-controller) are expected to run
on the SmartNIC OS which will have a different hostname from the hypervisor
OS which results in a mismatch during port binding (more specifically to the
OVS case, the external_ids[“hostname”] field in the Open_vSwitch table differs
from the hypervisor hostname). Likewise, representor plugging and flow
programming happens on the SmartNIC host, not on the hypervisor host. As a
result, Nova (with the help of os-vif) can no longer be responsible for VIF
plugging in the same way. For instance, compared to the OVS hardware offload
scenario, OVS bridges and port representors are no longer exposed to the
hypervisor host OS. In summary, no networking agents are present on the
hypervisor host in this architecture. In this scenario the noop os-vif
plugin can be used to avoid explicit actions at the Nova host side, while
a different service at the SmartNIC DPU side will be responsible for
plugging of representors into the right bridge. However, Nova is still
responsible for passing the device information to the virt driver so that
it can be used when starting an instance.&lt;/p&gt;
&lt;p&gt;Since Nova and networking agents run on different hosts, there needs to be a
set of interactions in order to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Schedule an instance to a host where a VF with the necessary capability is
present;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select a suitable VF at the hypervisor host side and create a PCI device
claim for it;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the necessary logic as described in the Neutron specification &lt;a class="footnote-reference brackets" href="#id58" id="id11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;19&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The SmartNIC DPU selection in particular becomes an issue to address due to
the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;PF and VF mac addresses can be reprogrammed so they cannot be used as
reliable persistent identifiers to refer to SmartNIC DPUs;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PCI(e) add-in cards themselves do not have entries in sysfs but PCI(e)
endpoints do;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a SmartNIC DPU uses PCIe to access the PCIe endpoints exposed by the
NIC, hypervisor hosts and SmartNIC DPU hosts do not see the same set of PCIe
functions as they see &lt;strong&gt;isolated PCIe topologies&lt;/strong&gt;. Each host enumerates the
PCIe topology it is able to observe. While the same NIC is exposed to both
topologies, the set of functions and config spaces observed by hosts differs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Note that SmartNIC DPUs may have different ways of accessing a
switchdev-capable NIC: via PCIe, a platform device or other means of I/O.
The hypervisor host would see PCIe endpoints regardless of that but relying
on PCI addresses in the implementation to match functions and their
representors is not feasible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to track SmartNIC DPUs and associations of PFs/VFs with them, there
is a need for a unique and persistent identifier that is discoverable from both
hypervisor hosts and SmartNIC DPU hosts. PCI (2.1+) and PCIe specifications
define the Vital Product Data (VPD) capability which includes a serial number
field which is defined to be unique and read-only for a given add-in card. All
PFs and VFs exposed by a PCI(e) card share the same VPD data (whether it is
exposed on PFs only or VFs is firmware-specific). However, this field is
currently not gathered by the virt drivers or recorded by the Nova
PciResourceTracker (note: SmartNIC DPUs from several major vendors are known
to provide VPD with serial numbers filled in and visible from hypervisor hosts
and SmartNIC DPU hosts).&lt;/p&gt;
&lt;p&gt;The serial number information exposed via PCI(e) VPD is also available via
devlink-info - there are no ties to a particular IO standard such as PCI(e) so
other types of devices (e.g. platform devices) could leverage this as well.&lt;/p&gt;
&lt;p&gt;For the PCI(e) use-case specifically, there is a need to distinguish the
PFs/VFs that simply expose a VPD from the ones that also need to be associated
with SmartNIC DPUs. In order to address that, PCI devices can be tagged using
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough_whitelist&lt;/span&gt;&lt;/code&gt; to show that they are associated with a
SmartNIC DPU.&lt;/p&gt;
&lt;p&gt;Reliance on the “switchdev” capability (persisted into the extra_info column
of pci_devices table) is also problematic since the PFs exposed to a hypervisor
host by the NIC on a SmartNIC DPU board do not provide access to the NIC
Switch - it is not possible to query whether the NIC Switch is in the “legacy”
or “switchdev” mode from the hypervisor side. This has to do with NIC internals
and the way the same NIC is exposed to hypervisor host CPUs and the
“application CPU” on the add-in card. Devlink documentation in the kernel
provides an example of that with two PCIe hierarchies: &lt;a class="footnote-reference brackets" href="#id48" id="id12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The main use-case is to support allocation of VFs associated with off-path
SmartNIC DPUs and their necessary configuration at the SmartNIC DPU side;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From the operator perspective, being able to use multiple SmartNIC DPUs per
host is desirable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="desired-outcome-overview"&gt;
&lt;h3&gt;Desired Outcome Overview&lt;/h3&gt;
&lt;p&gt;The following points summarize the desired outcome:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Off-path&lt;/strong&gt; SmartNIC DPUs from various vendors where networking control
plane components are meant to run on SmartNIC DPU hosts;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reuse of the existing VNIC type “smart-nic” (VNIC_SMARTNIC);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A new tag for PCI devices to indicate that a device is associated with a
SmartNIC DPU: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote_managed=True|False&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for multiple SmartNIC DPUs per host;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No expectation that the hypervisor host will be responsible for placing an
image onto a SmartNIC DPU directly;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a security boundary is assumed between the main board host and the
SmartNIC/DPU;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Indirect communication between Nova and software running on the SmartNIC
DPU;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Focus on the libvirt virt driver for any related changes initially but make
the design generic for other virt drivers to follow;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Configuration and deployment of the SmartNIC DPU and its control plane software
on it is outside the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The scope of this change is in Nova but it is a part of a larger effort that
involves OVN and Neutron.&lt;/p&gt;
&lt;p&gt;Largely, the goal is to gather the information necessary for representor
plugging via Nova and pass it to the right place.&lt;/p&gt;
&lt;p&gt;In case PCIe used at the SmartNIC DPU for NIC access, both the hypervisor host
and the SmartNIC DPU host that belong to the same physical machine can see
PCI(e) functions exposed by the controllers on the same card, therefore, they
can see the same unique add-in-card serial number exposed via VPD. For other
types of I/O, devlink-info can be relied upon to retrieve the board serial
(if available). This change, however, is focused on the PCI and will use PCI
VPD info as seen by Libvirt.&lt;/p&gt;
&lt;p&gt;Nova can store the information about the observed cards and use it later during
the port update process to affect the selection of a SmartNIC DPU host that
will be used for representor plugging.&lt;/p&gt;
&lt;p&gt;Device tags in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough_whitelist&lt;/span&gt;&lt;/code&gt; will tell Nova which PCI
vendor and device IDs refer to functions belonging to a SmartNIC DPU.&lt;/p&gt;
&lt;p&gt;The following needs to be addressed in the implementation:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Store VPD info from the PCI(e) capability for each PciDevice;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;card_serial_number - a string of up to 255 bytes since PCI and PCIe specs
use a 1-byte length field for the SN;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info:&lt;/span&gt; &lt;span class="pre"&gt;'{"capabilities":&lt;/span&gt; &lt;span class="pre"&gt;"vpd":&lt;/span&gt; &lt;span class="pre"&gt;{"card_serial_number":&lt;/span&gt; &lt;span class="pre"&gt;"&amp;lt;sn&amp;gt;"}]'}&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieval of the PCI card serial numbers stored in PCI VPD as presented in
node device XML format exposed by Libvirt for PFs and VFs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Whether or not PCI VPD is exposed for VFs as well as PFs is specific to
the device firmware (sometimes there is an NVRAM option to enable to expose
this data on VFs in addition to PFs) - it might be useful to populate
VF-specific information based on the PF information in case PCI VPD is not
exposed for VFs;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store the card serial number information (if present) in the PciDevice
extra_info column under the “vpd” capability;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough_whitelist&lt;/span&gt;&lt;/code&gt; handling implementation to take
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote_managed=True|False&lt;/span&gt;&lt;/code&gt; tag into account;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each function added to an instance, collect a PF MAC and VF logical
number as seen by the hypervisor host and pass them to Neutron along with
the card serial number during port update requests that happen during
instance creation (see the relevant section below for more details);&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Note that if VFIO is used, this specification assumes that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vfio-pci&lt;/span&gt;&lt;/code&gt;
driver will only be bound to VFs, not PFs and that PFs will be utilized for
hypervisor host purposes (e.g. connecting to the rest of the control
plane);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storing of VF logical number and PF MAC could be in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info&lt;/span&gt;&lt;/code&gt; could
be done to avoid extra database lookups;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add logic to handle ports of type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; (“remote-managed”);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new Nova compute service version constant
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SUPPORT_VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt;) and an instance build-time check (in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_validate_and_build_base_options&lt;/span&gt;&lt;/code&gt;) to make sure that instances with this
port type are scheduled only when all compute services in all cells have this
service version;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The service version check will need to be triggered only for network
requests containing port_ids that have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; port
type. Nova will need to learn to query the port type by its ID to perform
that check;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new compute driver capability called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;supports_remote_managed_ports&lt;/span&gt;&lt;/code&gt;
and a respective &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_REMOTE_MANAGED_PORTS&lt;/span&gt;&lt;/code&gt; trait to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-traits&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Only the Libvirt driver will be set to have this trait since this is the
first driver to support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote_managed&lt;/span&gt;&lt;/code&gt; ports;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a prefilter that will check for the presence of port ids that have
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; port type and add the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_REMOTE_MANAGED_PORTS&lt;/span&gt;&lt;/code&gt; to the request spec in this case. This
will make sure that instances are scheduled on compute nodes that have the
necessary virt driver supporting remote managed ports enabled;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add compute service version checks for the following operations for instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; ports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create server;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach a VNIC_TYPE_REMOTE_MANAGED port;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPES_DIRECT_PASSTHROUGH&lt;/span&gt;&lt;/code&gt;
list since Nova instance lifecycle operations like live migration will be
handled in the same way as other VNIC types already present there;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid waiting for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;network-vif-plugged&lt;/span&gt;&lt;/code&gt; events for active ports with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; ports.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="identifying-port-representors"&gt;
&lt;h3&gt;Identifying Port Representors&lt;/h3&gt;
&lt;p&gt;This specification makes an assumption that Neutron will be extended to act
upon the additional information passed from Nova. The following set of
information is proposed to be sent during a port update:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;card serial number;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PF mac address (seen both by the hypervisor host and the SmartNIC DPU host);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VF logical number.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is needed to do the following multiplexing decisions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Determining the right SmartNIC DPU hostname associated with a chosen VF.
There may be multiple SmartNIC DPUs per physical host. This can be done by
associating a card serial number with a SmartNIC DPU hostname at the Neutron
&amp;amp; OVN side (Nova just needs to pass it in a port update);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Picking the right NIC Switch at the SmartNIC DPU side. PF logical numbers
are tied to controllers &lt;a class="footnote-reference brackets" href="#id48" id="id13" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id50" id="id14" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;11&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Typically there is a single NIC and
NIC Switch in a SmartNIC but there is no guarantee that there will not be a
device with multiple of those. As a result, just passing a PF logical number
from the hypervisor host is not enough to determine the right NIC Switch.
A PF MAC address could be used as a way to get around the lack of visibility
of a controller at the hypervisor host side;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choosing the right VF representor - a VF logical number tied to a particular
PF.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PF and controller numbers seen by the SmartNIC DPU are not visible from the
hypervisor host since it does not see the NIC Switch. To further expand on
this, the devlink &lt;a class="footnote-reference brackets" href="#id49" id="id15" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;10&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; infrastructure in the kernel supports different port
flavors (quoted descriptions originate from linux/uapi/linux/devlink.h &lt;a class="footnote-reference brackets" href="#id51" id="id16" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;12&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;physical - “any kind of a port physically facing the user”. PFs on the
hypervisor side and uplink ports on the SmartNIC DPU will have this flavor;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;virtual - “any virtual port facing the user”. VFs on the hypervisor side will
have this flavor;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pcipf - an NIC Switch port representing a port of PCI PF;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pcivf - an NIC Switch port representing a port of PCI VF.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Linux kernel exposes logical numbers via devlink differently for different
port flavors:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;physical and virtual flavors: via DEVLINK_ATTR_PORT_NUMBER - this value is
driver-specific and depends on how a device driver populates those
attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pcipf and pcivf flavors: DEVLINK_ATTR_PORT_PCI_PF_NUMBER and
DEVLINK_ATTR_PORT_PCI_VF_NUMBER attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, for a NIC with 2 uplink ports with sriov_numvfs set to 4 for
both uplink ports at the hypervisor side, the set of interfaces as shown by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devlink&lt;/span&gt; &lt;span class="pre"&gt;port&lt;/span&gt;&lt;/code&gt; will be as follows:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f0&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;physical&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f1&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;physical&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f1np0v0&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.4&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f1np0v1&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.5&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f1np0v2&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;02.6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f1np0v3&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f0np0v0&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.4&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f0np0v1&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.5&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f0np0v2&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;enp5s0f0np0v3&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notice the virtual port indexes are all set to 0 - in this example the device
driver does not provide any indexing information via devlink attributes for
“virtual” ports.&lt;/p&gt;
&lt;p&gt;SmartNIC DPU host &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devlink&lt;/span&gt; &lt;span class="pre"&gt;port&lt;/span&gt;&lt;/code&gt; output:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;262143&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;p0&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;physical&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;196608&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf0hpf&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcipf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;196609&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf0vf0&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;196610&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf0vf1&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;196611&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf0vf2&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;196612&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf0vf3&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;327679&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;physical&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;262144&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf1hpf&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcipf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;262145&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf1vf0&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;262146&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf1vf1&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;262147&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf1vf2&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;262148&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="n"&gt;netdev&lt;/span&gt; &lt;span class="n"&gt;pf1vf3&lt;/span&gt; &lt;span class="n"&gt;flavour&lt;/span&gt; &lt;span class="n"&gt;pcivf&lt;/span&gt; &lt;span class="n"&gt;pfnum&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;vfnum&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So the logical numbers for representor flavors are correctly identified at the
SmartNIC DPU but are not visible at the hypervisor host.&lt;/p&gt;
&lt;p&gt;VF PCI addresses at the hypervisor side are calculated per the PCIe and SR-IOV
specs using the PF PCI address, “First VF Offset” and “VF Stride” values and
the logical per-PF numbering is maintained by the kernel and exposed via sysfs.
Therefore, we can take logical VF numbers from the following sysfs entries:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pf_pci_addr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;virtfn&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vf_logical_num&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;They can also be accessed via:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pci&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;vf_pci_addr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;physfn&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;virtfn&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vf_logical_num&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Finding the right entry via a physfn symlink can be done by resolving virtfn
symlinks one by one and comparing the result with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vf_pci_addr&lt;/span&gt;&lt;/code&gt; that
is of interest.&lt;/p&gt;
&lt;p&gt;As for finding the right PF representor by a MAC address of hypervisor host PF,
it depends on the availability of information about a mapping of a hypervisor
PF MAC to a PF representor MAC.&lt;/p&gt;
&lt;p&gt;VF logical number and PF MAC information can be extracted at runtime right
before a port update since those are done by the Nova Compute manager during
instance creation. Alternatively, it can be stored in the database in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_info&lt;/span&gt;&lt;/code&gt; of a PciDevice.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vf-vlan-programming-considerations"&gt;
&lt;h3&gt;VF VLAN Programming Considerations&lt;/h3&gt;
&lt;p&gt;Besides NIC Switch capability not being exposed to the hypervisor host,
SmartNIC DPUs also may prevent VLAN programming by for VFs, therefore,
operations like the following will fail (see, &lt;a class="footnote-reference brackets" href="#id65" id="id17" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;26&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; for the example driver
code causing it which was later fixed in &lt;a class="footnote-reference brackets" href="#id66" id="id18" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;27&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;enp130s0f0&lt;/span&gt; &lt;span class="n"&gt;vf&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;vlan&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;fe&lt;/span&gt;
&lt;span class="n"&gt;RTNETLINK&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;permitted&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case the VF MAC programming is allowed by the driver, however, VLAN
programming is not.&lt;/p&gt;
&lt;p&gt;Nova does not tell Libvirt to program VLANs for VIFs with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIFHostDeviceDevType.ETHERNET&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id67" id="id19" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;28&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; (it explicitly passes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; for the
vlan parameter to &lt;a class="footnote-reference brackets" href="#id68" id="id20" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;29&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;) which are going to be used in the implementation.&lt;/p&gt;
&lt;p&gt;Libvirt only programs a specific VLAN number for hostdev ports &lt;a class="footnote-reference brackets" href="#id69" id="id21" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;30&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIR_DOMAIN_NET_TYPE_HOSTDEV&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id70" id="id22" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;31&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;) if one is provided via device XML and
otherwise tries to clear a VLAN by passing a VLAN ID 0 to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RTM_SETLINK&lt;/span&gt;&lt;/code&gt;
operation (handing of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EPERM&lt;/span&gt;&lt;/code&gt; in this case is addressed by &lt;a class="footnote-reference brackets" href="#id61" id="id23" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;22&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Nova itself only programs a MAC address and VLAN for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_MACVTAP&lt;/span&gt;&lt;/code&gt;
ports &lt;a class="footnote-reference brackets" href="#id71" id="id24" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;32&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id72" id="id25" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;33&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, therefore, the implementation of this specification does
not need to introduce any changes for that.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The main points that were considered when looking for alternatives:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Code reuse: a lot of work went into the hardware offload implementation and
extending it without introducing new services and projects would be
preferable;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security and isolation: SmartNICs DPUs are isolated from the hypervisor host
intentionally to create a security boundary between the hypervisor services
and network services. Creating agents to drive provisioning and configuration
from the hypervisor itself would remove that benefit;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIC Switch configuration and port plugging: services running on a
SmartNIC DPU need to participate in port representor plugging and NIC Switch
programming which is not necessarily specific to Nova or even OpenStack.
Other infrastructure projects may benefit from that as well so the larger
effort needs to concentrate on reusability. This is why possible
introduction of SmartNIC DPU-level services specific to OpenStack needs to be
avoided (i.e. it is better to extend OVN to do that and handle VF plugging at
the Nova side).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One alternative approach involves tracking cards using a separate service with
its own API and possibly introducing a different VNIC type: this does not have
a benefit of code reuse and requires another service to be added and integrated
with Nova and Neutron at minimum. Evolving the work that was done to enable
hardware offloaded ports seems like a more effective way to address this
use-case.&lt;/p&gt;
&lt;p&gt;Supporting one SmartNIC DPU per host initially and extending it at a later
point has been discarded due to difficulties in the data model extension.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;PciDevices get additional information associated with them without affecting
the DB model:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;a “vpd” capability which stores the information available in the PCI(e) VPD
capability (initially, just the board serial number but it may be extended at
a later point if needed).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Periodic hypervisor resource updates will add newly discovered PciDevices and
get the associated card serial number information. However, old devices will
not get this information without explicit action.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Additional steps need to be performed to extract serial number information of
PCI(e) add-in cards from the PFs and VFs exposed by them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Reading PCI(e) device VPD is supported since kernel 2.6.26
(see kernel commit 94e6108803469a37ee1e3c92dafdd1d59298602f) and devices
that support PCI local bus 2.1+ (and any PCIe revision) use the same binary
format for it. The VPD capability is optional per the PCI(e) specs, however,
production SmartNICs/DPUs observed so far do contain it (engineering samples
may not have VPD so only use generally available hardware for this).&lt;/p&gt;
&lt;p&gt;During the deployment planning it is also important to take control traffic
paths into account. Nova compute is expected to pass information to Neutron
for port binding via the control network: Neutron is then responsible for
interacting with OVN which then propagates the necessary information to
ovn-controllers running at SmartNIC DPU hosts. Also, Placement service updates
from hypervisor nodes happen over the control network. This may happen via
dedicated ports programmed on the eSwitch which needs to be done via some form
of a deployment automation. Alternatively, LoMs on many motherboards may be
used for that communication but the overall goal is to remove the need for
that. The OOB port on the SmartNIC DPU (if present) may be used for control
communication too but it is assumed that it will be used for PXE boot of an OS
running on the application CPU and for initial NIC Switch configuration. Which
interfaces to use for control traffic is outside of the scope of this
specification and the purpose of this comment is to illustrate the possible
indirect communication paths between components running on different hosts
within the same physical machine and remote services:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                       ┌────────────────────────────────────┐
                       │  Hypervisor                        │    LoM Ports
                       │  ┌───────────┐       ┌───────────┐ │   (on-board,
                       │  │ Instance  │       │  Nova     │ ├──┐ optional)
                       │  │ (QEMU)    │       │ Compute   │ │  ├─────────┐
                       │  │           │       │           │ ├──┘         │
                       │  └───────────┘       └───────────┘ │            │
                       │                                    │            │
                       └────────────────┬─┬───────┬─┬──┬────┘            │
                                        │ │       │ │  │                 │
                                        │ │       │ │  │ Control Traffic │
                           Instance VF  │ │       │ │  │ PF associated   │
                                        │ │       │ │  │ with an uplink  │
                                        │ │       │ │  │ port or a VF.   │
                                        │ │       │ │  │ (used to replace│
                                        │ │       │ │  │  LoM)           │
   ┌────────────────────────────────────┼─┼───────┼─┼──┼─┐               │
   │   SmartNIC DPU Board               │ │       │ │  │ │               │
   │                                    │ │       │ │  │ │               │
   │  ┌──────────────┐ Control traffic  │ │       │ │  │ │               │
   │  │   App. CPU   │ via PFs or VFs  ┌┴─┴───────┴─┴┐ │ │               │
   │  ├──────────────┤  (DC Fabric)    │             │ │ │               │
   │  │ovn-controller├─────────────────┼─┐           │ │ │               │
   │  ├──────────────┤                 │ │           │ │ │               │
   │  │ovs-vswitchd  │     Port        │ │NIC Switch │ │ │               │
   │  ├──────────────┤   Representors  │ │  ASIC     │ │ │               │
   │  │    br-int    ├─────────────────┤ │           │ │ │               │
   │  │              ├─────────────────┤ │           │ │ │               │
   │  └──────────────┘                 │ │           │ │ │               │
   │                                   │ │           │ │ │               │
   │                                   └─┼───┬─┬─────┘ │ │               │
 ┌─┴──────┐Initial NIC Switch            │   │ │       │ │               │
─┤OOB Port│configuration is done via     │   │ │uplink │ │               │
 └─┬──────┘the OOB port to create        │   │ │       │ │               │
   │       ports for control traffic.    │   │ │       │ │               │
   └─────────────────────────────────────┼───┼─┼───────┼─┘               │
                                         │   │ │       │                 │
                                      ┌──┼───┴─┴───────┼────────┐        │
                                      │  │             │        │        │
                                      │  │   DC Fabric ├────────┼────────┘
                                      │  │             │        │
                                      └──┼─────────────┼────────┘
                                         │             │
                                         │         ┌───┴──────┐
                                         │         │          │
                                     ┌───▼──┐  ┌───▼───┐ ┌────▼────┐
                                     │OVN SB│  │Neutron│ │Placement│
                                     └──────┘  │Server │ │         │
                                               └───────┘ └─────────┘
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Processes on the hypervisor host would use the PF associated with an uplink
port or a bond (or VLAN interfaces on top of those) in order to communicate
with control processes.&lt;/p&gt;
&lt;p&gt;SmartNIC DPUs themselves do not typically have a BMC themselves and draw
primary power from a PCIe slot so their power lifecycle is tied to the
main board lifecycle. This should be taken into consideration when performing
power off/power on operations on the hypervisor hosts as it will affect
services running on the SmartNIC DPU (a reboot of the hypervisor host should
not).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The current specification targets the libvirt driver - other virt drivers
need to gain similar functionality to discover card serial numbers if they
want to support the same workflow.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;section id="nova-service-versions"&gt;
&lt;h4&gt;Nova Service Versions&lt;/h4&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Proposed&lt;/span&gt; &lt;span class="pre"&gt;Change&lt;/span&gt;&lt;/code&gt; section discusses adding a service version constant
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SUPPORT_VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt;) and an instance build-time check across
all cells. For operators, the upgrade impact will be such that this feature
will not be possible to use until all Nova Compute services will be upgraded to
support this service version.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="neutron-integration"&gt;
&lt;h4&gt;Neutron integration&lt;/h4&gt;
&lt;p&gt;This section focuses on operational concerns with regards to Neutron being able
to support instances booted with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; port type.&lt;/p&gt;
&lt;p&gt;At the time of writing, only the OVS mechanism driver supports &lt;a class="footnote-reference brackets" href="#id52" id="id26" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;13&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_TYPE_REMOTE_MANAGED&lt;/span&gt;&lt;/code&gt; ports but only if a particular configuration
option is set in the Neutron OpenvSwitch Agent (which was done for Ironic
purposes, not Nova &lt;a class="footnote-reference brackets" href="#id53" id="id27" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;14&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Therefore, in the absence of mechanism drivers that would support ports of that
type or when the mechanism driver is not configured to handle ports of that
type, port binding will fail.&lt;/p&gt;
&lt;p&gt;This change also relies on the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id54" id="id28" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;15&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; which
does not have a strict format and documented as:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;dictionary&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;enables&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;
&lt;span class="k"&gt;pass&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;receive&lt;/span&gt; &lt;span class="n"&gt;vif&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;networking&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;networking&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;does&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Therefore, no Neutron API changes are needed to support additional attributes
specified passed by Nova in port updates.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dmitriis&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;fnordahl, james-page&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Support the PCI &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vpd&lt;/span&gt;&lt;/code&gt; capability exposed by Libvirt via node device XML;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement modifications to store the card serial number information
associated with PciDevices;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_passthrough_whitelist&lt;/span&gt;&lt;/code&gt; to include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote_managed&lt;/span&gt;&lt;/code&gt;
tag handling;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add handling for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VNIC_SMARTNIC&lt;/span&gt;&lt;/code&gt; VNIC type;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement VF logical number extraction based on virtfn entries in sysfs:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/sys/bus/pci/devices/{pf_pci_addr}/virtfn&amp;lt;vf_logical_num&amp;gt;&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend the port update procedure to pass an add-in-card serial number,
PF mac and VF logical number to Neutron in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile&lt;/span&gt;&lt;/code&gt; attribute;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement service version checking for the added functionality;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a prefilter to avoid scheduling instances to nodes that do not
support the right compute capability;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit testing coverage;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Function tests for the added functionality;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration testing with other projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;In order to make this useful overall there are additional cross-project
changes required. Specifically, to make this work with OVN:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ovn-controller needs to learn how to plug representors into correct bridges
at the SmartNIC DPU node side since the os-vif-like functionality to hook VFs
up is still needed;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Representor plugging and related OVN changes: &lt;a class="footnote-reference brackets" href="#id55" id="id29" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;16&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id56" id="id30" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;17&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id63" id="id31" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;24&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id64" id="id32" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;25&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The OVN driver code in Neutron needs to learn about SmartNIC DPU node
hostnames and respective PCIe add-in-card serial numbers gathered via VPD:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Port binding needs to be aware of the hypervisor and SmartNIC DPU
hostname mismatches and mappings between card serial numbers and SmartNIC
DPU node hostnames. The relevant Neutron RFE is in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rfe-approved&lt;/span&gt;&lt;/code&gt;
state &lt;a class="footnote-reference brackets" href="#id57" id="id33" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;18&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; the relevant Neutron specification is published at
&lt;a class="footnote-reference brackets" href="#id58" id="id34" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;19&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, while the code for it is tracked in &lt;a class="footnote-reference brackets" href="#id59" id="id35" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;20&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;);&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt supports parsing PCI/PCIe VPD and as of October 2021 &lt;a class="footnote-reference brackets" href="#id60" id="id36" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;21&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and
exposes a serial number if it is present in the VPD;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt tries to clear a VLAN if one is not specified (trying to set VLAN ID
to 0), however, some SmartNIC DPUs do not allow the hypervisor host to do
that since the privileged NIC switch control is not provided to it. A patch
to Libvirt &lt;a class="footnote-reference brackets" href="#id61" id="id37" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;22&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; addresses this issue.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="future-work"&gt;
&lt;h3&gt;Future Work&lt;/h3&gt;
&lt;p&gt;Similar to the hardware offload &lt;a class="footnote-reference brackets" href="#id46" id="id38" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; functionality, this specification does
not address operational concerns around the selection of a particular device
family. The specification proposing PCI device tracking in the placement
service &lt;a class="footnote-reference brackets" href="#id62" id="id39" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;23&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; could be a step in that direction, however, it would likely
require Neutron extensions as well that would allow specifying requested device
traits in metadata associated with ports.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit testing of the added functionality;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional tests will need to be extended to support additional cases related
to the added functionality;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova admin guide needs to be extended to discuss &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remote_managed&lt;/span&gt;&lt;/code&gt; tags;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cross-project documentation needs to be written: Neutron and deployment
project guides need to be updated to discuss how to deploy a cloud with
SmartNIC DPUs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id40" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://netdevconf.info/0x14/pub/slides/39/Netdev%200x14%20--%20Taking%20Control%20of%20your%20SmartNIC%20v1.pdf"&gt;https://netdevconf.info/0x14/pub/slides/39/Netdev%200x14%20–%20Taking%20Control%20of%20your%20SmartNIC%20v1.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id41" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://homes.cs.washington.edu/~arvind/papers/ipipe.pdf"&gt;https://homes.cs.washington.edu/~arvind/papers/ipipe.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id42" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://man7.org/linux/man-pages/man7/ovn-architecture.7.html"&gt;https://man7.org/linux/man-pages/man7/ovn-architecture.7.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id43" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/Documentation/networking/switchdev.txt"&gt;https://www.kernel.org/doc/Documentation/networking/switchdev.txt&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id44" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://lwn.net/Articles/692942/"&gt;https://lwn.net/Articles/692942/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id45" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/html/latest/networking/devlink/index.html"&gt;https://www.kernel.org/doc/html/latest/networking/devlink/index.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id46" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id9"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id38"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-ovs-offload.html"&gt;https://docs.openstack.org/neutron/latest/admin/config-ovs-offload.html&lt;/a&gt;;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id47" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.snia.org/sites/default/orig/DSI2015/presentations/Rev/Jeff%20DodsonSNIA_Tutorial_PCIe_Shared_IO_2015_revision.pdf"&gt;https://www.snia.org/sites/default/orig/DSI2015/presentations/Rev/Jeff%20DodsonSNIA_Tutorial_PCIe_Shared_IO_2015_revision.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id48" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id12"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id13"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/html/latest/networking/devlink/devlink-port.html#pci-controllers"&gt;https://www.kernel.org/doc/html/latest/networking/devlink/devlink-port.html#pci-controllers&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id49" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id15"&gt;10&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/html/latest/networking/devlink/devlink-port.html#devlink-port"&gt;https://www.kernel.org/doc/html/latest/networking/devlink/devlink-port.html#devlink-port&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id50" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id14"&gt;11&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=66b17082d10a3b806eec3da8fdebe8a9cd2c6612"&gt;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=66b17082d10a3b806eec3da8fdebe8a9cd2c6612&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id51" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id16"&gt;12&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/torvalds/linux/blob/v5.12/include/uapi/linux/devlink.h#L191-L206"&gt;https://github.com/torvalds/linux/blob/v5.12/include/uapi/linux/devlink.h#L191-L206&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id52" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id26"&gt;13&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://opendev.org/openstack/neutron/src/tag/19.0.0/neutron/plugins/ml2/drivers/mech_agent.py#L109-L116"&gt;https://opendev.org/openstack/neutron/src/tag/19.0.0/neutron/plugins/ml2/drivers/mech_agent.py#L109-L116&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id53" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id27"&gt;14&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://opendev.org/openstack/ironic-specs/commit/f358fbdde9a1cadc838327b8bf34ee54a7e7f43a"&gt;https://opendev.org/openstack/ironic-specs/commit/f358fbdde9a1cadc838327b8bf34ee54a7e7f43a&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id54" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id28"&gt;15&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#id72"&gt;https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#id72&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id55" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id29"&gt;16&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://patchwork.ozlabs.org/project/ovn/list/?series=267834&amp;amp;state=3&amp;amp;archive=both"&gt;https://patchwork.ozlabs.org/project/ovn/list/?series=267834&amp;amp;state=3&amp;amp;archive=both&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id56" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id30"&gt;17&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://patchwork.ozlabs.org/project/ovn/list/?series=270569&amp;amp;archive=both&amp;amp;state=*"&gt;https://patchwork.ozlabs.org/project/ovn/list/?series=270569&amp;amp;archive=both&amp;amp;state=*&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id57" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id33"&gt;18&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1932154"&gt;https://bugs.launchpad.net/neutron/+bug/1932154&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id58" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;19&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id11"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id34"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/788821"&gt;https://review.opendev.org/c/openstack/neutron-specs/+/788821&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id59" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id35"&gt;20&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron/+/808961"&gt;https://review.opendev.org/c/openstack/neutron/+/808961&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id60" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id36"&gt;21&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://gitlab.com/libvirt/libvirt/-/commits/master?search=PCI.*VPD"&gt;https://gitlab.com/libvirt/libvirt/-/commits/master?search=PCI.*VPD&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id61" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;22&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id23"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id37"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://gitlab.com/libvirt/libvirt/-/commit/09cdd16a9bf73bc1f75fe774216c71f9ebc78c88"&gt;https://gitlab.com/libvirt/libvirt/-/commit/09cdd16a9bf73bc1f75fe774216c71f9ebc78c88&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id62" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id39"&gt;23&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/791047"&gt;https://review.opendev.org/c/openstack/nova-specs/+/791047&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id63" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id31"&gt;24&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/ovn-org/ovn-vif"&gt;https://github.com/ovn-org/ovn-vif&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id64" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id32"&gt;25&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/ovn-org/ovn-vif/pull/3"&gt;https://github.com/ovn-org/ovn-vif/pull/3&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id65" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id17"&gt;26&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/torvalds/linux/blob/v5.15/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c#L427-L434"&gt;https://github.com/torvalds/linux/blob/v5.15/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c#L427-L434&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id66" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id18"&gt;27&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7846665d3504812acaebf920d1141851379a7f37"&gt;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7846665d3504812acaebf920d1141851379a7f37&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id67" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id19"&gt;28&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/vif.py#L479-L485"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/vif.py#L479-L485&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id68" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id20"&gt;29&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/designer.py#L97-L105"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/designer.py#L97-L105&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id69" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id21"&gt;30&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/blob/7e6295cc7db2b11b28af7f4ef644f2dd30ea6840/src/conf/domain_conf.c#L29411-L29425"&gt;https://github.com/libvirt/libvirt/blob/7e6295cc7db2b11b28af7f4ef644f2dd30ea6840/src/conf/domain_conf.c#L29411-L29425&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id70" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id22"&gt;31&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/libvirt/libvirt/blob/7e6295cc7db2b11b28af7f4ef644f2dd30ea6840/src/conf/domain_conf.h#L904"&gt;https://github.com/libvirt/libvirt/blob/7e6295cc7db2b11b28af7f4ef644f2dd30ea6840/src/conf/domain_conf.h#L904&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id71" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id24"&gt;32&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/vif.py#L628-L640"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/vif.py#L628-L640&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id72" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id25"&gt;33&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/vif.py#L94-L102"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/virt/libvirt/vif.py#L94-L102&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>Store and allow libvirt instance device buses and models to be updated</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/libvirt-device-bus-model-update.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-device-bus-model-update"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-device-bus-model-update&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;QEMU support for device buses and models can come and go dependent on the
underlying instance machine type &lt;em&gt;and&lt;/em&gt; QEMU version used within an environment.
The defaults provided by libosinfo and currently hardcoded in to the libvirt
driver are not persisted by each instance at present.&lt;/p&gt;
&lt;p&gt;This spec aims to outline a basic set of nova-manage commands to allow
operators to move instances between specific device bus and model types without
requiring a rebuild.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present device bus and model types defined as image properties associated
with an instance are always used when launching instances with the libvirt
driver. When these types are not defined as image properties their values
either come from libosinfo or those directly hardcoded into the libvirt driver.&lt;/p&gt;
&lt;p&gt;Support for each device bus and model is dependent on the machine type used
&lt;em&gt;and&lt;/em&gt; version of QEMU available on the underlying compute host.&lt;/p&gt;
&lt;p&gt;As such any changes to the machine type of an instance or version of QEMU on a
host might suddenly invalidate the stashed device bus or model image
properties with no way of updating outside of a complete instance rebuild
against a new image defining new image properties.&lt;/p&gt;
&lt;p&gt;Additionally any changes to the defaults provided by libosinfo or the libvirt
driver could result in unforeseen changes to existing instances. This has been
encountered in the past as libosinfo assumes that libvirt domain definitions
are static when OpenStack Nova specifically rewrites and redefines these
domains during a hard reboot or migration allowing changes to possibly occur.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want the device buses and models used by my instance to remain
stable for as long as possible and not be changed by new defaults in
libosinfo or the OpenStack Nova libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to change the device bus or model of an instance
&lt;em&gt;without&lt;/em&gt; forcing users to fully rebuild the instance in order to accommodate
changing machine types or QEMU deprecations for certain types.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="register-existing-device-buses-and-models-within-system-metadata"&gt;
&lt;h3&gt;Register existing device buses and models within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt; we first want to ensure the current device bus and
model types associated with an instance are stashed ensuring they remain
stable during the lifetime of the instance. This already happens when these
buses or models are defined by image properties so we only need to capture
their value when these are not defined at either service startup or instance
creation time.&lt;/p&gt;
&lt;p&gt;The following list of image properties outline the list of device buses and
models this spec will aim to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_floppy_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_input_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pointer_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_video_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vif_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_rng_model&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_scsi_model&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_rescue_bus&lt;/span&gt;&lt;/code&gt; are not included
here as they have no default values. They must be defined to be used
negating the need for us to capture them here.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="provide-nova-manage-commands-to-update-existing-device-buses-and-models"&gt;
&lt;h3&gt;Provide nova-manage commands to update existing device buses and models&lt;/h3&gt;
&lt;p&gt;With the bus and model types stored we can now provide commands to operators to
inspect and update only the list of allowed image properties above:&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova-manage&lt;span class="w"&gt; &lt;/span&gt;image-property&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$instance&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova-manage&lt;span class="w"&gt; &lt;/span&gt;image-property&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$instance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Will list or show the stashed image properties of an instance.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova-manage&lt;span class="w"&gt; &lt;/span&gt;image-property&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--property&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hw_disk_bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scsi&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--property&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hw_scsi_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;virtio-scsi&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$instance&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Will update image properties of an instance, only accepting the previously
defined list of image properties for the time being.&lt;/p&gt;
&lt;section id="prerequisites"&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;The following prerequisites apply when attempting to update the image
properties of an instance:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The instance must be in a STOPPED, SHELVED or SHELVED_OFFLOADED vm_sate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The provided type will be validated against the corresponding versioned
object fields for the bus or model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once updated the user or admin can power on or unshelve the instance, causing
the underlying libvirt domain to be redefined using the new bus or model type.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None, other than providing a generic API to allow stashed image properties to
be updated by users over time without requiring a rebuild but that’s out of
scope for this basic nova-manage command spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users should now find that the device bus and models used by their instances
remain stable throughout their lifetime unless a move is forced upon them
by the operator, QEMU support deprecations etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Stashing these values will incur a slight overhead at compute service start
time when using the libvirt driver and additionally when spawning new
instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators should have more control over when and how they move users to
different machine types and versions of QEMU.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Register existing device buses and models within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide nova-manage commands to update existing device buses and models&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Extensive unit and functional tests will be written to validate this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operator/admin facing documentation will be written outlining the usecase for
these commands as well as the normal documentation for the commands themselves.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>Lightbits LightOS(TM) Nova Spec</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/nova-support-lightos-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-support-lightos-driver"&gt;https://blueprints.launchpad.net/nova/+spec/nova-support-lightos-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lightbits Labs(TM) (&lt;a class="reference external" href="http://www.lightbitslabs.com"&gt;http://www.lightbitslabs.com&lt;/a&gt;) LightOS(R) is software-defined,
cloud native, high-performance, scale-out and redundant clustered NVMe/TCP
storage that performs like local NVMe flash.&lt;/p&gt;
&lt;p&gt;The nova Lightbits LightOS libvirt volume driver works with LightOS
support for cinder and os_brick to enable openstack environments using
nova/libvirt to connect to LightOS storage clusters.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;LightOS provides persistent volume storage. In normal flow, cinder
triggers volume creation/deletion and attachment/detachment through
the nova libvirt LightOS volume driver. In abnormal conditions (e.g.,
when the nova node has gone down for reboot or power failure and then
come back up, or on nova restart) the volume driver queries which
instances exist on startup and what storage they were connected to (if
any). For any instances that were connected to LightOS, the libvirt
LightOS volume driver together with the os_brick LightOS connector
will reestablish the connection to LightOS for those instances and
volumes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I would like to leverage LightOS with openstack to get
highly-performing (performs the same as local NVMe SSDs) remote
storage over NVMe/TCP for my openstack clouds, with failure-resistance
both on the storage drive level and the storage server level. I want
the performance of local NVMe drives with the convenience and
flexibility of remote storage, while knowing that I am secure and my
instances will remain connected to their storage even if drives and
storage nodes fail.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We add a new libvirt volume driver to nova that will provide
functionalities of attach, detach and extend to a LightOS cluster
volume, as well as querying which instances exist on startup (e.g.,
after reboot of power failure). This is being added concurrently with
the LightOS support for cinder and for os_brick.&lt;/p&gt;
&lt;p&gt;NVMe/TCP volumes are host mounted. The os_brick connector connects as
needed to the LightOS cluster via NVMe/TCP and exposes host device
files to the nova node. From the libvirt/QEMU point of view, the files
are then attached/detached to instances.&lt;/p&gt;
&lt;p&gt;Although LightOS works with VMware and other container and
virtualization environments as well, LightOS openstack support is
limited to libvirt-based environments.&lt;/p&gt;
&lt;p&gt;Live migration with multi-attach is fully supported and there are no
special network requirements. LightOS works via NVMe/TCP that works
over any TCP/IP network. The LightOS cluster needs to be reachable
(routable) over TCP/IP from the compute nodes and network bandwidh
should be provisioned to support the desired storage traffic.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The LightOS volumes are first mounted by the libvirt host, which then
passes them to QEMU as local host files to attach/detach to
instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;LightOS cluster must be installed and configured and the The Lightbits
Labs discovery-client service must run on compute nodes. For more
details, see the README included with the cinder driver:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/821602"&gt;https://review.opendev.org/c/openstack/cinder/+/821602&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Generally, there is no impact on upgrades.
During rolling upgrades where some compute nodes may have been upgraded
with LightOS support and some haven’t been upgraded yet, the operator should
use either traits or use a placement aggregate to make sure cinder only places
instances using LightOS storage on nova-computes that have been updated.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Yuval Brave (&lt;a class="reference external" href="mailto:yuval%40lightbitslabs.com"&gt;yuval&lt;span&gt;@&lt;/span&gt;lightbitslabs&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;create a new volume driver for lightos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;upgrade os-brick to use a new os-brick with the LightOS connector&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The LightOS libvirt volume driver requires the corresponding LightOS
cinder driver and os_brick support.  Cinder blueprint is at:
&lt;a class="reference external" href="https://blueprints.launchpad.net/cinder/+spec/cinder-lightos-driver"&gt;https://blueprints.launchpad.net/cinder/+spec/cinder-lightos-driver&lt;/a&gt;
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/821602"&gt;https://review.opendev.org/c/openstack/cinder/+/821602&lt;/a&gt;
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-brick/+/821603"&gt;https://review.opendev.org/c/openstack/os-brick/+/821603&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests were added to the patch. Lightbits LightOS third party CI
is hosted by Lightbits Labs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Documentation for configuring lightos storage will be added to:
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/cinder/+/821602/10"&gt;https://review.opendev.org/c/openstack/cinder/+/821602/10&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>Pick guest CPU architecture based on host arch in libvirt driver</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/pick-guest-arch-based-on-host-arch-in-libvirt-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pick-guest-arch-based-on-host-arch-in-libvirt-driver"&gt;https://blueprints.launchpad.net/nova/+spec/pick-guest-arch-based-on-host-arch-in-libvirt-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Implement new image meta property that allows for the selection of the
correct QEMU binary, cpu architecture, and machine type for a guest
architecture that is different than the host architecture; An x86_64
guest running on an AArch64 host, and vice versa.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, in many places, Nova’s libvirt driver makes decisions on how
to configure guest XML based on &lt;em&gt;host&lt;/em&gt; CPU architecture
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;caps.host.cpu.arch&lt;/span&gt;&lt;/code&gt;. That is not optimal in all cases where physical
hardware support is limited for non-traditional architectures.&lt;/p&gt;
&lt;p&gt;So all of the said code needs to be reworked to make those decisions
based on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;guest&lt;/span&gt;&lt;/code&gt; CPU architecture (i.e. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;guest.arch&lt;/span&gt;&lt;/code&gt;, which should be
set based on the image metadata property, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;A related piece of work is to distinguish between hosts that can do AArch64,
PPC64, Etc. via KVM (which is hardware-accelerated) vs. those that can only
do it via plain emulation &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TCG&lt;/span&gt;&lt;/code&gt; — this is to ensure that guests are not
arbitrarily scheduled on hosts that are incapable of hardware acceleration,
thus losing out on performance-related benefits.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to allow for cpu architecture emulation due to
constraints of or lack with alternate physical architecture types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to deploy AArch64, PPC64, MIPs, RISC-V, and
s390x as an emulated architecture on x86_64.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to deploy x86_64, PPC64, MIPs, RISC-V, and
s390x as an emulated architecture on AArch64.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new cpu architecture spec, an image property will
be introduced and an additional function which allows for checks and
comparisions between the host architecture and desired emulation architecture&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt;&lt;/code&gt; image property relates to the physical
architecture of the compute hosts. If physical nodes are not present for
the desired architecture then the instance will not be provisioned.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="retrieve-os-architecture-for-libvirtconfigguest"&gt;
&lt;h3&gt;Retrieve OS architecture for LibvirtConfigGuest&lt;/h3&gt;
&lt;p&gt;This leverages nova virt libvirt config to grab the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_arch&lt;/span&gt;&lt;/code&gt; and update
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt;&lt;/code&gt; image meta property with the retrieved value. With
this change we can perform the required comparisons within nova virt libvirt
driver for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt;&lt;/code&gt; values.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;os_arch&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;type_node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"arch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;os_arch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="allow-emulation-architecture-to-be-defined-by-image-property"&gt;
&lt;h3&gt;Allow emulation architecture to be defined by image property&lt;/h3&gt;
&lt;p&gt;To enable defining the guest architecture the following string based image
meta property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When this image property is not defined then instance provisioning will
occur as normal. The process is demonstrated below via the 3 examples.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example 1&lt;/strong&gt; When both image meta properties are set the emulation
architecture will take precedent, and it will build on a X86_64 host that
supports emulatating AARCH64 or whatever supported architecture is inputted
in place of AARCH64.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;AARCH64&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;X86_64&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example 2&lt;/strong&gt; When the emulation image meta property is set the emulation
architecture will take precedent, and it will build on any host that
supports emulating X86_64 or whatever supported architecture is inputted
in place of X86_64.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;X86_64&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;unset&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example 3&lt;/strong&gt; When the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt;&lt;/code&gt; property is unset it
will build on any host that natively supports the specified architecture.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;unset&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;AARCH64&lt;/span&gt;&lt;/code&gt; OR &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;X86_64&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="update-scheduler-request-filter-to-handle-both-architecture-fields"&gt;
&lt;h3&gt;Update scheduler request_filter to handle both architecture fields&lt;/h3&gt;
&lt;p&gt;Within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transform_image_metadata&lt;/span&gt;&lt;/code&gt; function, we will add the two
architecture properties to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;prefix_map&lt;/span&gt;&lt;/code&gt;. this in itself also requires
additional os-traits to be added for both &lt;strong&gt;hw&lt;/strong&gt; and &lt;strong&gt;compute&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;transform_image_metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_spec&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Transform image metadata to required traits.&lt;/span&gt;

&lt;span class="sd"&gt;    This will modify the request_spec to request hosts that support&lt;/span&gt;
&lt;span class="sd"&gt;    virtualisation capabilities based on the image metadata properties.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_metadata_prefilter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;prefix_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'hw_cdrom_bus'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE_STORAGE_BUS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'hw_disk_bus'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE_STORAGE_BUS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'hw_video_model'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE_GRAPHICS_MODEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'hw_vif_model'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE_NET_VIF_MODEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'hw_architecture'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'HW_ARCH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'hw_emulation_architecture'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE_ARCH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="update-os-traits"&gt;
&lt;h3&gt;Update os-traits&lt;/h3&gt;
&lt;p&gt;Below are the os-traits proposed for the compute cpu architectures to be
supported for emulatation, where as the hardware architecture includes all
current nova supported architectures within nova objects fields.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;TRAITS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'AARCH64'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'PPC64LE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'MIPSEL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'S390X'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'RISCV64'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'X86_64'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To account for the emulation of these architectures, updates will be made
to the nova virt libvirt driver ensuring that compute capability traits
are reported for each architecture emulator that is available on the hosts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="perform-architecture-test-against-emulation"&gt;
&lt;h3&gt;Perform architecture test against emulation&lt;/h3&gt;
&lt;p&gt;To facilitate a simple check throughout the nova virt libvirt driver the
following function does a check and will set the appropriate guest
architecture based on emulation, if defined.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;_check_emulation_arch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image_meta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;emulation_arch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image_meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hw_emulation_architecture"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;emulation_arch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;arch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emulation_arch&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;arch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libvirt_utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_arch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_meta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arch&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Utilization of the actual check performed through processing the image_meta
dictionary values.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;arch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_check_emulation_arch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_meta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="proposed-emulated-architectures-and-current-support-level"&gt;
&lt;h3&gt;Proposed emulated architectures and current support level&lt;/h3&gt;
&lt;p&gt;All testing performed with changes proposed in this spec demonstrated that
the emulated guests maintain current support for all basic lifecycle actions.
Listed below are the proposed architectures and there current functional
level with the spec, with the plan of all being &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Tested&lt;/span&gt; &lt;span class="pre"&gt;and&lt;/span&gt; &lt;span class="pre"&gt;validated&lt;/span&gt; &lt;span class="pre"&gt;for&lt;/span&gt;
&lt;span class="pre"&gt;functional&lt;/span&gt; &lt;span class="pre"&gt;support&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;X86_64&lt;/span&gt;&lt;/code&gt; - Tested and validated for functional support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AARCH64&lt;/span&gt;&lt;/code&gt; - Tested and validated for functional support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PPC64LE&lt;/span&gt;&lt;/code&gt; - Tested and validated for functional support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MIPSEL&lt;/span&gt;&lt;/code&gt; - Awaiting libvirt patch for PCI support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;S390X&lt;/span&gt;&lt;/code&gt; - Troubleshooting guest kernel crash for functional support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RISCV64&lt;/span&gt;&lt;/code&gt; - To be Tested&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Other attempts have been made leverage existing image meta properties such
as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_architecture&lt;/span&gt;&lt;/code&gt; only; however, this opens various other issues with
conflicting check and alterations of core code. This also runs into issues
during the scheduling of instances as there will be no matching physical
host architectures, which is what this spec aims to solves.&lt;/p&gt;
&lt;p&gt;While the best option is providing actual physical support for the
cpu architectures you want to test, this opens the ability to a wider
audience to perform the same type of local emulation they can with QEMU
within an openstack environment.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Adds a new set of standard traits to os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adds new property to image_meta objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The OS arch value will be pulled into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigGuest&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This is expected to improve boot performance in a heterogeneous cloud
by reducing reschedules. By passing a more constrained request to
placement this feature should also reduce the resulting set of
allocation_candidates that are returned.&lt;/p&gt;
&lt;p&gt;This will also ensure that native support is handled first over emulation
as it requires a specific property to be set in order to perform the
required checks.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Ensure that all the desired QEMU binaries are installed on the physical
nodes for the cpu architectures that you would like to support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;chateaulav - Jonathan Race&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update prefilter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify nova libvirt virt driver to perform checks for emulation architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new property to image_meta objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify nova libvirt virt config to pull OS arch into LibvirtConfigGuest&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Blueprint&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pick-guest-arch-based-on-host-arch-in-libvirt-driver"&gt;https://blueprints.launchpad.net/nova/+spec/pick-guest-arch-based-on-host-arch-in-libvirt-driver&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Project Changesets&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/822053"&gt;https://review.opendev.org/c/openstack/nova/+/822053&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/824050"&gt;https://review.opendev.org/c/openstack/os-traits/+/824050&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Libvirt MIPs PCI Bug&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1432101"&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1432101&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests will be added for validation of the following proposed changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;nova virt libvirt driver&lt;/strong&gt; to validate handling of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_emulation_architecture&lt;/span&gt;&lt;/code&gt; image property value and associated checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;nova scheduler request_filter&lt;/strong&gt; to ensure proper handling of the
prefilter, with added the two new values.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Proposed updates to tempest will account for the non-native architectures
being supported through emulation.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;AARCH64 architecture will be tested with every patch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remaining architectures will be tested with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic-weekly&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;experimental&lt;/span&gt;&lt;/code&gt; pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A release note will be added. As there is enduser impact, user facing
documentation will be required for the supported emulation architecture
types and the required image meta properties to need to be set.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2022-January/026544.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2022-January/026544.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pick-guest-arch-based-on-host-arch-in-libvirt-driver"&gt;https://blueprints.launchpad.net/nova/+spec/pick-guest-arch-based-on-host-arch-in-libvirt-driver&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>QoS minimum guaranteed packet rate</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/qos-minimum-guaranteed-packet-rate.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/qos-minimum-guaranteed-packet-rate"&gt;https://blueprints.launchpad.net/nova/+spec/qos-minimum-guaranteed-packet-rate&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Similarly to how bandwidth can be a limiting factor of a network interface,
packet processing capacity tend to be a limiting factor of the soft switching
solutions like OVS. In the same time certain applications are dependent on not
just guaranteed bandwidth but also on guaranteed packet rate to function
properly. OpenStack already supports bandwidth guarantees via the
&lt;a class="reference external" href="https://docs.openstack.org/api-ref/network/v2/?expanded=#qos-minimum-bandwidth-rules"&gt;minimum bandwidth QoS policy rules&lt;/a&gt;. This specification is aiming for adding
support for a similar minimum packet rate QoS policy rule.&lt;/p&gt;
&lt;p&gt;To add support for the new QoS rule type both Neutron and Nova needs to be
extended. This specification covers the high level description of these
impacts, the interaction between Neutron, Placement and Nova. And have
the details of the Nova specific changes necessary. For the detailed
description of the Neutron impact please see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;OpenStack needs to provide support for minimum packet rate guarantees on
Neutron ports via a new QoS policy rule type.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;I as an administrator want to define the maximum packet rate, in kilo packet
per second (kpps), my OVS soft switch capable of handle per compute node, so
that I can avoid overload on OVS.&lt;/p&gt;
&lt;p&gt;I as an end user want to define the minimum packet rate, in kilo packet per
second (kpps) a Neutron port needs to provide to my Nova server, so that my
application using the port can work as expected.&lt;/p&gt;
&lt;p&gt;I as an administrator want to get a Nova server with such ports placed on a
compute node that can still provide the requested minimum packet rate for the
Neutron port so that the application will get what it requested.&lt;/p&gt;
&lt;p&gt;I as an administrator want that the nova server lifecycle operations are
rejected in case the requested minimum packet rate guarantee of the Neutron
ports of the server cannot be fulfilled on any otherwise eligible compute
nodes, so that the OVS overload is avoided and application guarantees are kept.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The whole solution is very similar and the proposed implementation heavily
rely on the already implemented &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/stein/implemented/bandwidth-resource-provider.html"&gt;qos guaranteed minimum bandwidth feature&lt;/a&gt;.&lt;/p&gt;
&lt;section id="new-resources"&gt;
&lt;h3&gt;New resources&lt;/h3&gt;
&lt;p&gt;The solution needs to differentiate between two deployment scenarios.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The packet processing functionality is implemented on a shared hardware
(e.g. on the same compute host CPUs) and therefore both ingress and egress
queues are handled by the same hardware resources. This is the case in the
non-hardware-offloaded OVS deployments. In this scenario OVS represents a
single packet processing resource pool. Which can be represented with a
single new resource class, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The packet processing functionality is implemented in a specialized hardware
where the ingress and egress queues are processed by independent
hardware resources. This is the case for hardware-offloaded OVS. In this
scenario a single OVS has two independent resource pools one for the
incoming packets and one for the outgoing packets. Therefore these needs to
be represented with two new resource classes
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_EGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_IGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;1 kilo packet means 1000 packets in the context of packet rate resource.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;These new resource classes needs to be added to Placement’s os-resource-classes
library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="packet-processing-resource-inventory"&gt;
&lt;h3&gt;Packet processing resource inventory&lt;/h3&gt;
&lt;p&gt;The bandwidth resources are modelled on the OVS physnet bridges as each bridge
is connected to a specific physical NIC that provides the bandwidth resource.
As the packet processing resource is provided by the OVS service itself
therefore the packet processing resource needs to be modeled on an entity that
is global for the whole OVS service. Today we have such entity, the Neutron OVS
agent itself. This assumes that one Neutron OVS agent only handles one OVS
which is true today. We think this assumption is strong one. If later on two
vswitches are needed on the same compute host then we think it is easier to
duplicate the agents handling them separately than enhancing the current agent
to handle two switches.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="resource-inventory-reporting"&gt;
&lt;h3&gt;Resource inventory reporting&lt;/h3&gt;
&lt;p&gt;For details of these Neutron changes please see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Neutron OVS agent needs to provide configuration options for the
administrator to define the maximum packet processing capacity of the OVS
per compute node. Depending on the deployment scenario this might mean a
single directionless inventory value, or two direction aware values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron agent needs to communicate the configured capacity to the Neutron
server via the agent hearth beat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron server needs to report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_[E|I]GR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; resource inventory on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Open&lt;/span&gt; &lt;span class="pre"&gt;vSwitch&lt;/span&gt; &lt;span class="pre"&gt;agent&lt;/span&gt;&lt;/code&gt; resource provider to Placement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="requesting-minimum-packet-rate-guarantees"&gt;
&lt;h3&gt;Requesting minimum packet rate guarantees&lt;/h3&gt;
&lt;p&gt;For details of these Neutron changes please see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Neutron QoS API needs to be extended with the new minimum packet rate QoS rule
type. The rules of this type need to be persisted in the neutron DB similarly
to the other QoS rules.&lt;/p&gt;
&lt;p&gt;To support the two different OVS deployment scenario we need two sets of new
minimum guaranteed QoS rule types. One which is directionless to support the
case when the resource is also directionless. And two other that are direction
aware to support the other deployment case where the pps resource are also
direction aware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="nova-servers-with-the-new-qos-policies"&gt;
&lt;h3&gt;Nova servers with the new QoS policies&lt;/h3&gt;
&lt;p&gt;Today Neutron expresses the resource needs of a port via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field. The value of this field is intended to communicate
the resource needs in a generic, machine readable way. Nova and
(and indirectly Placement) uses this during the scheduling of the server to
decide which compute host can fulfill the overall resource needs of the server
including the ports of the server. So far the port can only have bandwidth
resource request.&lt;/p&gt;
&lt;p&gt;To support the new packet rate resource Neutron API needs to be changed so that
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; read only field of the port could contain more than
one group of requested resources and required traits. Today the content of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; is translated to a single, named Placement request group
during scheduling. As a single port can have both bandwidth and packet rate QoS
applied and because bandwidth is allocated from the bridge / physical device
while the packet rate resource is allocated from the whole OVS instance the two
groups of resources need to be requested separately. The technical reason to
this is that a single named resource request group is always allocated from a
single resource provider in Placement. So if bandwidth and packet rate does not
need to come from the same resource provider then they should be requested in
different resource request groups.&lt;/p&gt;
&lt;p&gt;The new format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"request_groups"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="s2"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_VNIC_TYPE&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;NET_PACKET_RATE_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;GR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="n"&gt;requested&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;QoS&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="s2"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_PHYSNET_&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_VNIC_TYPE&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NET_BW_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;GR_KILOBIT_PER_SEC&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;requested&lt;/span&gt; &lt;span class="n"&gt;bandwidth&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;the&lt;/span&gt; &lt;span class="n"&gt;QoS&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"same_subtree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;above&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;above&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For the reasoning why we need this format see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Neutron port binding API needs to be extended. Today the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation&lt;/span&gt;&lt;/code&gt;
key in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile&lt;/span&gt;&lt;/code&gt; of the port is used by Nova to communicate the
UUID of the resource provider from which the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; of the port
is fulfilled from. This is then used by the Neutron’s port binding logic to
bind the port to the same physical device the Placement resource is allocated
from. Now that a port can request resources from more than one placement
resource providers a single UUID is not enough to communicate where those
resources are allocated from. Nova needs to provide a mapping instead that
describes which set of resource, a.k.a which request group, is fulfilled from
which resource provider in placement.&lt;/p&gt;
&lt;p&gt;For the details of the new structures see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="adapting-nova-to-the-neutron-changes"&gt;
&lt;h3&gt;Adapting Nova to the Neutron changes&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova needs to adapt to the changes in the structure and semantics of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field of the neutron port. Today Nova translates this
field to a single named resource request group. After the Neutron changes
this field will communicate a list of such request groups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova also assumes today that a port only allocates resource from a single
resource provider. This assumption needs to be removed and the implementation
needs to support a list of such resource providers. Nova can still assume
that a single placement request group is fulfilled by a single resource
provider as that is an unchanged Placement behavior.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These Nova changes needs to be applied to every code path in Nova that results
in a new scheduling attempt including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;server create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;migrate, resize, evacuate, live-migrate, unshelve after shelve-offload&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;interface attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="what-is-out-of-scope"&gt;
&lt;h3&gt;What is out of scope&lt;/h3&gt;
&lt;p&gt;Supporting minimum packet rate policy for other than OVS backends are out of
scope but can be handled later with a similar proposal.&lt;/p&gt;
&lt;p&gt;This spec only aiming to give scheduling time guarantees for the packet
rate. The data plane enforcement of the new policy is out of scope. When the
&lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1912460"&gt;packet rate limit policy rule&lt;/a&gt; feature is implemented then a basic data plane
enforcement can be applied by adding both minimum and maximum packet rate QoS
rules to the same QoS policy where maximum limit is set to be equal to the
minimum guarantee.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="id1"&gt;
&lt;h4&gt;Packet processing resource inventory&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Alternatively&lt;/em&gt; it was suggested to define the packet processing inventory
on the OVS bridge level. The big advantage of having the pps resource
represented on the OVS bridge, on the same place as the bandwidth resource, is
that it would simplify the overall design. It would means that we could still
keep the assumption that the resource request of the port is always fulfilled
from a single resource provider. Therefore the format of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile.allocation&lt;/span&gt;&lt;/code&gt; does not need to
change. However there are a list of counter arguments against this direction:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If we define packet processing capacity on the bridges then if there are
multiple bridges then the overall packet processing capacity of the whole OVS
would need to be statically split between the bridges, while the actual
resource usage of OVS are not split in that way in reality.
Configuration with multiple bridges are possible today, even in the
frequently used case of having one phynet bridge for VLAN traffic and one
tunneling bridge for the VXLAN traffic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In case of bandwidth the actual resource is behind the physnet bridge, the
physical interface the bridge is connected to, so the resource is dedicated
to the bridge. But in case of packet processing the actual resource is not at
all dedicated to the given bridge but it is dedicated to the whole OVS
instance. So while we can assign a portion of the overall resource to the
bridge this assignment would never represent the reality well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Traffic between the VMs on the same host does not flow through the physnet or
tunneling bridges but it does impact the capacity of the OVS on the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While the currently proposed design change is significant it makes the
solution more future proof. E.g. for the case when the IP pool resource
handling will be refactored to use the port’s resource_request then we anyhow
need to be able to handle another resource provider that will not be the same
as any of the existing ones as the IP addresses are shared resource between
multiple host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Another alternative&lt;/em&gt; would be to represent the packet processing capacity on a
new provider that maps to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-int&lt;/span&gt;&lt;/code&gt; the OVS integration bridge where the VMs
are plugged. This have the benefit that the resource inventory would be global
on OVS instance level and also it would clean up some of the confusion created
by having a separate OVS Agent RP. Moving further we could even consider
dropping the Agent RP altogether and only representing the bridge hierarchy in
Placement with the resource provider hierarchy. Logically it is not different
from that we rename today’s OVS Agent RP to br-int RP. However &lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2021-05-21.log.html#t2021-05-21T10:33:22"&gt;we agreed&lt;/a&gt;
that keep this as a future exercise if and when more OVS instances would be
needed per OVS agent.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="id2"&gt;
&lt;h4&gt;Requesting minimum packet rate guarantees&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Alternatively&lt;/em&gt; it was suggested that it would be enough to have a single set
of direction aware QoS rule types. Then in case of the normal OVS deployment
scenario, where the resource is directionless, the resource requests from the
direction aware QoS rules could be added together before matched against the
single directionless resource inventory. Neutron would be able to differentiate
between the two deployment situation on the port level based on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; of the port. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;normal&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; means that the port is
requested to be backed by a normal OVS with directionless resource accounting.
While the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; means the port is requested to be backed by
a hardware-offloaded OVS (or non OVS backend, like SRIOV) with a direction
aware resource inventory.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;No Placement DB schema changes expected.&lt;/p&gt;
&lt;p&gt;For the Neutron DB changes see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No Nova DB schema changes are expected.&lt;/p&gt;
&lt;p&gt;Some Nova o.v.o changes are expected.&lt;/p&gt;
&lt;p&gt;The RequestSpec object already stores a list of RequestGroups as it needs to
support multiple ports and cyborgs devices per Instance already.&lt;/p&gt;
&lt;p&gt;The RequestGroup object does not assume anything about the format of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt; field. However the parts of nova that drives the PCI claim
based on the already allocated bandwidth assumes that the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest.requester_id&lt;/span&gt;&lt;/code&gt; is the same &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;port_id&lt;/span&gt;&lt;/code&gt; as the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup.requester_id&lt;/span&gt;&lt;/code&gt;. To facilitate distinction between different
groups requested by the same port this assumption needs to be removed. This
needs a new field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_id&lt;/span&gt;&lt;/code&gt; in the RequestGroup object that stores the
group id from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requested_resources&lt;/span&gt;&lt;/code&gt; while we keep the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt;
to be the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;port_id&lt;/span&gt;&lt;/code&gt; as today. The PCI request update logic needs to be
changed to use the group with the bandwidth resource to drive the PCI claim.
This creates an unfortunate dependency between the Nova code and the content
of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt;. We can remove this dependency one we start
modeling PCI devices in Placement.&lt;/p&gt;
&lt;p&gt;The RequestLevelParams object also needs to be extended to store a list of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;same_subtree&lt;/span&gt;&lt;/code&gt; requests coming from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;same_subtree&lt;/span&gt;&lt;/code&gt; field of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;See the changes in the handling of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation&lt;/span&gt;&lt;/code&gt; key in the port’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile&lt;/span&gt;&lt;/code&gt; how this might change in the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Neutron related resource provider model in Placement needs to be extended
with a new inventory of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_EGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_IGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; resources on the OVS agent resource
providers if such resource inventory is configured in the related agent
configuration by the administrator. Also the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_VNIC_TYPE_&lt;/span&gt;&lt;/code&gt; that today
applied only to the bridge and device RPs needs to be reported on the OVS Agent
RP to facilitate proper scheduling. Note that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PHYSNET_&lt;/span&gt;&lt;/code&gt; traits are
not needed for the packet rate scheduling as this resource is not split
between the available physnets.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;For the Neutron REST API changes see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This feature does not change the Nova API, only adapts Nova to be able to
consume the new Neutron API extension. A Nova microversion alone could not
signal the availability of the feature to the end user as with Xena Neutron
and Yoga Nova, even with latest Nova microversion, this feature will not be
available. Therefore no microversion bump will be added. What we suggest
instead is that the end users decide on feature availability based on what QoS
policies the admin created for them. If QoS policies with the new minimum
guaranteed QoS policy rule is available to the end users then they can be sure
that the feature is available. See the &lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2021-05-21.log.html#t2021-05-21T10:51:46"&gt;IRC log&lt;/a&gt; for further discussion.&lt;/p&gt;
&lt;p&gt;If, due to scoping, support for some of the lifecycle operations is not
implemented in the current release cycle then those operations will be rejected
with HTTP 400.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be extra calls to the Neutron &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/extensions&lt;/span&gt;&lt;/code&gt; API during the
server lifecycle operations to detect which format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt;
is used by Neutron and what format the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile.allocation&lt;/span&gt;&lt;/code&gt; is
expected by Neutron. This is temporary to support an upgrade scenario where
Nova is already upgraded to Yoga but Neutron isn’t. In Z release we can
remove the extra call and assume that Neutron always returns the new format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;No new configuration option is proposed to Nova but to use this feature Neutron
needs to be properly configured. See &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt; for details.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;OpenStack needs to support deployments where the major version of Neutron and
Nova are different. This means that changes for this feature needs to be
written to support both cases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Xena Neutron - Yoga Nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yoga Neutron - Xena Nova&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neutron will introduce a new API extension that will change the structure and
the semantic of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field of the port. Nova needs to
check the existence of the new API extension and parse the field accordingly.&lt;/p&gt;
&lt;p&gt;As Nova in Xena merged the changes, except the nova-manage changes, to support
the new Neutron API extension, such extension can be enabled by default in
Neutron in Yoga. The Yoga Neutron will work with Xena Nova properly.&lt;/p&gt;
&lt;p&gt;In the other hand Yoga Nova needs to understand both the old Neutron API if
Neutron is still on Xena level, and the new API if Neutron is also upgraded
to Yoga.&lt;/p&gt;
&lt;p&gt;As the changes impacting the nova-compute service a new service version
will be introduced. Nova will reject any lifecycle operation
(server created, delete, migration, resize, evacuate, live-migrate, unshelve
after shelve-offload, interface attach and detach) with HTTP 400 if the new
Neutron API extension is enabled but there are compute services in the
deployment with old service version not supporting the new extension.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Reject all lifecycle operations with HTTP 400 if the Neutron API extension
changing the structure of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field is enabled.
As we add support for each operation the rejection is removed from the given
operation. This way whenever we hit feature freeze we will have a consistent
system that rejects what is not supported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Propose the new resource classes to Placement’s os-resource-classes library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; parsing logic to support the new format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the new parsing logic if the new Neutron API extension is enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each lifecycle operation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Remove assumption from the code that a single port only request a single
request group. If this requires a nova-compute change then bump the service
version and add a check to the API side to reject the operation if there
are old computes in the cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the operation by removing the automatic rejection and keeping only
the service version check.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt the implementation of the nova-manage placement heal_allocation CLI to
the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new Neutron API extension for the port’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; as defined
in the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Integration testing can be done in the upstream CI system with the standard
OVS backend through tempest. The hardware-offloaded OVS case cannot be tested
in upstream CI.&lt;/p&gt;
&lt;p&gt;Top of the automatically assumed unit test coverage an extensive set of
functional test will be added to cover the relevant lifecycle operations with
ports having either just minimum packet rate QoS policy rules or both minimum
bandwidth and minimum packet rate QoS rules.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-guide/compute/port_with_resource_request.html"&gt;API guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/ports-with-resource-requests.html"&gt;Admin guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document Nova’s expectation on the format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field
of the Neutron port in the developer documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt; complementing this spec about the neutron details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron RFE for &lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1912460"&gt;packet rate limit policy rule&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced and merged support for the new Neutron API extension except
in the nova-manage placement heal_allocations CLI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed to finish up the nova-manage part&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 25 Mar 2022 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result operators need to ensure that Manila
backend storage is routable from the guest subnets.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not
be covered by this spec, any requests to shelve, evacuate, resize, cold migrate
or live migrate an instance with a share attached will be rejected with a
HTTP409 response for the time being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
once &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;support lands in libvirt itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://libvirt.org/kbase/virtiofs.html#other-options-for-vhost-user-memory-setup"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.
(ref: &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user documentation&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Two new compute capability traits and filters will be introduced to model an
individual compute’s support for virtio-fs and file backed memory.
And while associating a share to an instance, a check will ensure the host
running the instance will support the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and either the&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; trait&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;that the instance is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;From an operator’s point of view, it means
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt; support requires that
operators must upgrade all their compute nodes to the version supporting
shares using virtiofs.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt; support requires that operators configure one or
more hosts with file backed memory. Ensuring the instance will land on one of
these hosts can be achieved by creating an AZ englobing these hosts.
And then instruct users to deploy their instances in this AZ.
Alternatively, operators can guide the scheduler to choose a suitable host
by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_MEM_BACKING_FILE=required&lt;/span&gt;&lt;/code&gt; as an extra spec or
image property.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the users with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;p&gt;Share mapping status:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                     &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;   &lt;span class="n"&gt;Reboot&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
    &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;--------------+&lt;/span&gt;
    &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;mounted&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;active&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;umount&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;error&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+-------------+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-------------&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="n"&gt;φ&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fail&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;mount&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Detach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;VM&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Attach&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Share&lt;/span&gt; &lt;span class="n"&gt;unmounted&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="n"&gt;v&lt;/span&gt;                                 &lt;span class="n"&gt;v&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+--------------&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="n"&gt;inactive&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;+----------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;φ&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means no entry in the database. No association between a share and a server.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Attach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means POST /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Detach share&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;means DELETE /servers/{server_id}/shares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This chart describe the share mapping status (nova), this is independent from
the status of the Manila share.&lt;/p&gt;
&lt;p&gt;Share attachment/detachment can only be done if the VM state is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;.
These are operations only on the database, and no RPC calls will be required
to the compute API. This is an intentional design for this spec.
As a result, this could lead to situation where the VM start operation fails
as an underlying share attach fails.&lt;/p&gt;
&lt;p&gt;Mount operation will be done when the share is not mounted on the compute host.
If a previous share would have been mounted on the compute host for another
server, then it will attempt to mount it and a warning will be logged that
the share was already mounted.&lt;/p&gt;
&lt;p&gt;Umount operation will be really done when the share is mounted and not used
anymore by another server.&lt;/p&gt;
&lt;p&gt;With the above mount and umount operation, the state is stored in memory and
do not require a lookup in the database.&lt;/p&gt;
&lt;p&gt;The share will be mounted on the compute host using read/write mode.
Read-only will not be supported as a share could not be mounted read-only
and read/write at the same time. If the user wants to mount the share
read-only, it will have to do it in the VM fstab.&lt;/p&gt;
&lt;p&gt;Manila share removal issue:&lt;/p&gt;
&lt;p&gt;Despite a share being used by instances, it can be removed by the user.
As a result, the instances will lose access to the data and might cause
difficulties in removing the missing share and fixing the instance.
This is an identified issue that requires Manila modifications.
A solution was identified with the Manila team to attach metadata to the share
access-allow policy that will lock the share and prevent its deletion until
the lock is not removed.
If the above Manila change can land in the Zed cycle,
the proposal here is to use the lock mechanism in Nova.
Otherwise, clearly document the known issue as unsupported and warn users that
they should take care and avoid this pitfall.&lt;/p&gt;
&lt;p&gt;Instance metadata:&lt;/p&gt;
&lt;p&gt;Add instace shares in the instance metadata.
Extend DeviceMetadata with ShareMetadata object containing &lt;cite&gt;shareId&lt;/cite&gt; and
&lt;cite&gt;tag&lt;/cite&gt; used to mount the virtiofs on an instance by the user.
See &lt;a class="reference internal" href="#other-end-user-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PROJECT_ADMIN will be able to see details of the attachment id and export
location stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instance should have the required capabilities to enable
virtiofs (see above).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a synchronous API. As a result, the VM share attachement state
is defined in the database and set as inactive.
Then, power on the VM will do the required operations to attach the share and
set it as active if there are no errors.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter in the request body, when not
provided it will be the shareId(UUID) as always provided in the request.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; if povided by the user must be an ASCII string with a maximum
lenght of 64 bytes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Primary key autoincrement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;inactive&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within
the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the
underlying host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_proto&lt;/span&gt;&lt;/code&gt; - The Shared File Systems protocol (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NFS&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CEPHFS&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;The database field &lt;cite&gt;status&lt;/cite&gt; and &lt;cite&gt;share_proto&lt;/cite&gt; values will not be enforced
using enums allowing future changes and avoid database migrations.
However, to make code more robust, enums will be defined on the object fields.&lt;/p&gt;
&lt;p&gt;Fields containing text will use String and not Text type in the database schema
to limit the column width and be stored inline in the database.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to mount the
share to the host and the host filesystem location should
not be logged by Nova and only accessible by default through the API by admins.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One to add new notifications for share attach and share detach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One to extend the instance update notification with the share mapping
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Share mapping in the instance payload will be optional and controlled via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include_share_mapping&lt;/span&gt;&lt;/code&gt; notification configuration parameter. It will be
disabled by default.&lt;/p&gt;
&lt;p&gt;Proposed payload for attached and detached notification will be the same as
the one returned by the show command with admin rights.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Proposed instance payload for instance updade, will be the list of share
attached to this instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7754440a-1cb7-4d5b-b357-9b37151a4f2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-ffffffffffff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7987"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server2.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="id8"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Users could use the instance metadata to discover and auto mount the share.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.
While there will be near local performance between the vm and host,
the actual performance will be limited by the network performance of
the network file share protocol and hardware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and capability traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla (rene.ribaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (initial contributor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;uggla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new capability traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 14 Mar 2022 00:00:00 </pubDate></item><item><title>Unified Limits Integration in Nova</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/implemented/unified-limits-nova.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unified-limits-nova"&gt;https://blueprints.launchpad.net/nova/+spec/unified-limits-nova&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec is about adopting Keystone’s unified-limits.
Includes using oslo.limit to enforce the Nova related limits set in Keystone.&lt;/p&gt;
&lt;p&gt;This spec proposes having unified limits in parallel with the existing
quota system for at least one cycle, to allow for operators to transition
from setting quotas via Nova to setting limits relating to the Nova API
endpoint via Keystone.&lt;/p&gt;
&lt;p&gt;All per user quota support is dropped, in favor of hierarchical
enforcement that will be supported by unified limits.&lt;/p&gt;
&lt;p&gt;Only server count limits and limits on Resource Class resources requested in
the flavor will be supported with unified limits. All other existing quotas
will no longer support per project or per user limits.&lt;/p&gt;
&lt;p&gt;Given this placement focused approach, we will depend on the work done here:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;While much work has been done to simplify how quotas are implemented in
Nova, there are still some major usability issues for operators with
the current system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We don’t have consistent support for limit/quota hierarchy across OpenStack&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requiring operators to set limits individually in each service
(i.e. Cinder, Nova, Neutron, etc)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova’s existing quotas don’t work well with Ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No support for custom Resource Class quotas (includes “per flavor” quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confusion when API defined quota limits override any changes made to the
configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some Nova quotas are unrelated to resource consumption, causing confusion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transitioning to use Keystone’s unified limits, via oslo.limit, will help fix
these issues.&lt;/p&gt;
&lt;p&gt;For more details on unified limits in keystone see:
&lt;a class="reference external" href="https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html"&gt;https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The key use cases driving this work are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API User tries to understand why they got an Over Quota error&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator migrates to unified limits from existing limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator sets a default limit for a given endpoint via Keystone. Note there
can be different limits for each Region, even with a shared Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator sets specific limits for a given project via Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator defines limits of a set of projects via non-flat enforcement
i.e. the feature formally known as hierarchical quotas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will focus on adding unified limits relating to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;total number of servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amounts of each Resource Class requested in the flavor&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note, this includes things like DISK_GB which is not supported today,
along with things like custom resource class resources that are requested
in extra specs (e.g. Ironic flavors).&lt;/p&gt;
&lt;p&gt;We will now look at all quotas exposed via the API and what they map to
when using unifed limits:
&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota"&gt;https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The follow existing quota types move to unified limits, allowing for
per endpoint defaults and per project overrides (and hierarchical limits)
via the unified limits system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cores&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;class:VCPU&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ram&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;class:MEMORY_MB&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following existing quota becomes defined only by registered (default)
limits in the unified limits system, and we no longer support and per project
or user overrides via the API, we just report the existing limit as defined in
Keystone.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_pairs&lt;/span&gt;&lt;/code&gt; (counted per user) -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_key_pairs&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt; (counted per project)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt; (counted per server group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;metadata_items&lt;/span&gt;&lt;/code&gt; (counted per server) -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_metadata_items&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above are purely protecting database bloat (i.e to stop a denial
of service attack that fills up the database). They are similar to the
hardcoded limit of the number of tags you can attach to a server.&lt;/p&gt;
&lt;p&gt;While deprecated in the API, we will also treat these quotas in the
same way as the quotas above, i.e. they will now be set via
registered limits with no per project overrides possible:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_content_bytes&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_path_length&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_files&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are several parts to this spec:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enforce Unified Limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No per-user limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No uncountable limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate Nova’s Quota APIs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator tooling to assist with the migration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="enforcing-unified-limits"&gt;
&lt;h3&gt;Enforcing Unified Limits&lt;/h3&gt;
&lt;p&gt;We will support the following limits:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;class:&amp;lt;RESOURCE_CLASS&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_key_pairs&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_metadata_items&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the resource class usage will be counted using placement, but
server count will make use of instance mappings. This only works if the
queued for delete data migration has been completed. Due to no user
based quotas, we don’t need the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; migration. If the operator
tries to use unified limits before completing the migration, the code
will block all new usage until the migration is completed. It is
expected a blocking migration will be added before we turn on unified
limits by default. For more details on the this data migration see
this point in the existing quota code:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053"&gt;https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To allow the new system to co-exist with the older quota system, we make
use of the existing quota driver sytem. The default will be unchanged,
but operators can opt-into the new system in the following way:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For further details on the transition, please see the update section of this
specification. Note the new unified limits code will have a hard dependency
on counting usage via placement; as such it will ignore the value of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.quota.count_usage_from_placement&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the existing quotas, &lt;cite&gt;instances&lt;/cite&gt; becomes &lt;cite&gt;servers&lt;/cite&gt;,
&lt;cite&gt;cores&lt;/cite&gt; becomes &lt;cite&gt;class:VCPU&lt;/cite&gt; and &lt;cite&gt;ram&lt;/cite&gt; becomes &lt;cite&gt;class:MEMORY_MB&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;This work will re-use a lot of the new logic to query placement for resource
usage, and use the instance mapping table to count servers added in this spec:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To find out what resources a server will claim, we reuse this
code to extract the resources from any given flavor:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387"&gt;https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For server build, we use the above function to get the Resource Class
resource amounts for the requested flavor. This will then be checked using
olso.limit, which ensures the additional usage will not push the associated
project over any of its limits. The oslo.limit library is responsible for
counting all the current resource usage using a callback we provide that makes
use of placement to count the current resource usage.&lt;/p&gt;
&lt;p&gt;Once resources are claimed in placement, we optionally recheck the limits
to see if we were racing with other server builds to consume the last bits
of available quota. The only change is using oslo.limit to do the recheck.
That is, we will still respect the config: &lt;cite&gt;quota.recheck_quota&lt;/cite&gt;
Note: we do the first check of limits in nova-api, and the recheck in
nova-conductor after resource allocation in placement succeeds.&lt;/p&gt;
&lt;p&gt;It is a similar story with resize. Except in this case, we check that we can
claim resources for both the new flavor and old flavor at the same time.
Note that this is quite different to the current quota system, even when
counting usage via placement.&lt;/p&gt;
&lt;p&gt;For further details on the semantic changes relating to counting with
placement see:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note baremetal instances no longer claim any VCPU or MEMORY_MB resources.
With this method, baremetal instances can be limited using custom
resource class resources they request in the flavor.&lt;/p&gt;
&lt;p&gt;Should we choose to allow additional custom inventory entries
from hypervisor based compute nodes, such as &lt;cite&gt;{‘CUSTOM_GPU_V100’:1}&lt;/cite&gt;
we will be also be able to apply quotas on these resources.&lt;/p&gt;
&lt;p&gt;The oslo.limits library will likely add additional configuration options.
In particular, operators will need to specify the Nova API’s endpoint uuid
to oslo.limit, so it knows what unified limits apply to each particular
Nova API service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="no-per-user-limits"&gt;
&lt;h3&gt;No per user limits&lt;/h3&gt;
&lt;p&gt;Nova currently supports “per user” limits. They will no longer be supported
when: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are no plans for migration tools, however it is expected that users
that need a similar model can test out using the unified limits support for
hierarchical limits, and report back on what could help others migrate.&lt;/p&gt;
&lt;p&gt;Note: Keypairs will still have a max limit enforced, and that max limit
will still be enforced per user. However, there will now only be a single
default registered limit value in Keystone to set the max number of keypairs
each user is allowed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="no-uncountable-limits"&gt;
&lt;h3&gt;No uncountable limits&lt;/h3&gt;
&lt;p&gt;As stated above, the focus for unified limits is the instance count and
resource class allocations in placement.&lt;/p&gt;
&lt;p&gt;There are limits that are specific to nova-network. These are all ready
deprecated. There are no plans to support these with unified limits turned on:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixed_ips&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;floating_ip&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security_group_rules&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;networks&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The remaining limits are all mainly used to protect the database from rogue
users using up all available space in the database and/or missuse the API as
some sort of storage system. As such, it is not expected that operators need
per project overrides for any of these limits.&lt;/p&gt;
&lt;p&gt;The following limits will be changed to only be set via registered limits in
the unified limits system that applies equally to all projects:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_metadata_items&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_key_pairs&lt;/span&gt;&lt;/code&gt; (counted per user)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt; (counted per project)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt; (counted per server group)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the server_group_members are currently counted per user, but this
is frankly very confusing, so above we propose the simpler limit servers
in the server group. This seems consistent with removing per user limits for
all other project owned resources.&lt;/p&gt;
&lt;p&gt;Using registered limits only means:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;no per project overrides&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;no per user overrides&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are limits on the amount of data that can be stored in various
Nova databases. There is no way to display a project’s usage of these limits,
which further demonstrates how these are different to the resource limits
unified limits has been designed for.&lt;/p&gt;
&lt;p&gt;Currently we honor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; for all of these quotas. This adds
significant code complexity, however most users never hit these limits and
they are all very soft limits. As such, when we transition to a single default
registered limit value for all of these, we also will stop doing any rechecks.&lt;/p&gt;
&lt;p&gt;In summary the impact on the configuration options is:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; will have an updated description, noting what
functionality is lost when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.floating_ips&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.fixed_ips&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.security_groups&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security_group_rules&lt;/span&gt;&lt;/code&gt;: remain deprecated, and will be ignored when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.metadata_items&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_files&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_file_path_length&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.server_groups&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.server_group_members&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.key_pairs&lt;/span&gt;&lt;/code&gt;:  these will all be kept, but the description will be
updated to note if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; all
updates via the API are ignored.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="enforcement-of-limits"&gt;
&lt;h3&gt;Enforcement of limits&lt;/h3&gt;
&lt;p&gt;For consistency, all quota limits will be enforced using the &lt;a class="reference external" href="https://docs.openstack.org/oslo.limit/latest/user/usage.html#enforce-a-limit"&gt;oslo.limit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Enforcer.enforce&lt;/span&gt;&lt;/code&gt; API&lt;/a&gt;.
In this pattern, an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Enforcer&lt;/span&gt;&lt;/code&gt; object is initialized with a callback that
will count the existing usage of the resource being enforced. Some resources,
however, are counted only from the Nova API request payload in which they were
specified. We call these resource limits “API limits”:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_metadata_items&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, when a server create request is received in the Nova API and
metadata items are included in the request, we will compare the number of
metadata items requested with the quota limit for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_metadata_items&lt;/span&gt;&lt;/code&gt; and
we will not count anything in the database or placement as usage. An oslo.limit
quota limit enforcement involves a limit, a delta, and the current usage. For
API limits, we have only a limit and a delta. The current usage in these cases
will always be zero. As such, we initialize the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Enforcer&lt;/span&gt;&lt;/code&gt; object for API
limits with a callback that always returns zero usage. This way, oslo.limit can
do the enforcement properly using only the quota limit and the supplied delta.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;With unified limits, the behavior of VCPU and PCPU quota usage will change
to count VCPU resources independently from PCPU resources, consistent with
how they are represented in the placement service.&lt;/p&gt;
&lt;p&gt;Legacy quota behavior counts PCPU as VCPU and returns the sum of VCPU + PCPU
usage as the usage count for VCPU. A config option
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[workarounds]unified_limits_count_pcpu_as_vcpu&lt;/span&gt;&lt;/code&gt; will be provided  for
operators who require the legacy quota usage behavior where VCPU = VCPU +
PCPU. Note that if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;class:PCPU&lt;/span&gt;&lt;/code&gt; is specified in the flavor explicitly, it
will be expected to have its own unified limit registered and PCPU usage
will &lt;em&gt;not&lt;/em&gt; be merged into VCPU usage even when this option is set to True.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="deprecate-nova-s-quota-apis"&gt;
&lt;h3&gt;Deprecate Nova’s Quota APIs&lt;/h3&gt;
&lt;p&gt;To query and set limits, Keystones APIs should be used. To query a user’s
usage, the Placement API should be used, assuming placement is happy
changing the default policy to allow users to query their usage.&lt;/p&gt;
&lt;p&gt;The one exception is server count can’t currently be checked via
Placement. When placement implements consumer records,
or similar, then all usage could be queried via Placement. To avoid
using a proxy API, users can do a server list API and count the number
of servers returned.&lt;/p&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; a best effort will be
made to keep the older micro-versions working by proxing API calls to Keystone
and Placement as needed. No quota related DB tables will be accessed when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This includes the follow API resources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;/limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/os-quota-sets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/os-quota-class-sets&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing tooling to set quotas should continue to operate, as long as it only
changes quotas relating to instances, cores and ram. Requests to change any
other quotas will be silently ignored. As one example, this should allow
Horizon to function as normal during the transition.&lt;/p&gt;
&lt;p&gt;There are some trade-offs with this approach:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Proxy APIs suck, but horizon must keep working as such all current operator
tooling around these existing APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We don’t need a micro version to enable/disable this proxy
of the quota APIs, as it doesn’t really change the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a future release when unifed limits becomes the default,
we should deprecate the APIs
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-quota-sets&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-quota-class-sets&lt;/span&gt;&lt;/code&gt; and tell users to talk to
the Keystone API instead. API based discovery of when Nova is enforcing
the limits set in Keystone is left for a future spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is expected the above API deprecation will follow the pattern used
by nova-network proxy APIs, i.e. the APIs return 404 in new microversions
but continue to work in older microversions. Its possible in the more
distant future the APIs could be removed by returning 410 error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rejecting updates to quotas that we were previously able to set would be a
breaking change in behaviour, and require a microversion. Adding a new API
microversion that returns BadRequest for unsupported quotas would be a nice
addition if we were not planning on deprecating the API in favor of calling
Keystone instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideally we would also deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; in favor of a cross project
agreed direction that is aware of both flat and hierarchical limit
enforcement. Howerver we do not yet have consenus on what direction
we take. For this spec, we leave &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; in its current form, even
though it does not report on all the types of resource usage we now
support have limits on, and even though it lists limits that can
now only be changed via registered unified limits in Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When hierarchical limits are added, the per project usage information
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; does not mention anything about parent limits.
As such quota APIs may claim resources are available, but you will be
unable to build any new resources.
It is not clear what action the user can make to be able to build those new
resources. Operators can avoid this confusion by not over allocating quota.
We could extext the API to include a boolean to say if the limit has been
exceeded in the parent project, and as such the user is unable to consume
more resources even though their own usage is not over their own limits.
We could consider extending the API to include the usage of the full tree&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="migration-to-unified-limits"&gt;
&lt;h3&gt;Migration to Unified Limits&lt;/h3&gt;
&lt;p&gt;The migration of all users to unified limits is happening in three phases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;enable unified limits as an option, with migration path from existing quotas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;make unified limits the default, deprecate existing quota system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove existing quota system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To help with the transition we need operator tooling to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Set registered limits in Keystone for each Nova endpoint in Keystone,
based on current limits in DB and/or configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy per-project quotas set in Nova into Keystone unified-limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator confirms unified limits works for them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drop all quota info from the DB to signal operator has completed transition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade status check to check there is no data left in quota DB tables&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note the setting of project limits and registered limits in keystone will
happen via files that are generated and passed to keystone-manage. This
allows fast-forward upgrades where no API are available during the migration
of limits from Nova to Keystone.&lt;/p&gt;
&lt;p&gt;There will be a new tool to setup the registered limits in keystone. It will
read from the Nova DB and configuration and generate a file. That file can be
by used with keystone-manage to register the current endpoint defaults in
keystone.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;generate_registered_limits&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following tool will generate the unified limits overrides (if any)
that needs to be added into Keystone for each project. Again this too
produces a file that is handed to keystone-manage which will update keystone:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;generate_project_limits&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once the operator sets &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;, the
Nova DB is ignored, and limits are accessed from Keystone only.&lt;/p&gt;
&lt;p&gt;To complete the migration, there is an operation to remove all the DB entries
relating to the quota overrides. The tool only works when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;. It also removes all any per
user limits associated with each project.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;remove_db_quota_entries&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note the last two tools allow operators to iterate per project, to limit the
load on the running system. If these tools are used on a running system, it is
recommended that operators don’t change quotas via the API during the
transition.&lt;/p&gt;
&lt;p&gt;The nova status command will warn users that have failed to remove all the
quota information from the DB. This will become an error in the release when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver&lt;/span&gt;&lt;/code&gt; defaults to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is worth noting that the Nova database may contain entries for projects
that have been deleted in keystone. As such, it is advisable to get a list
of active projects from keystone, and only generate_project_limits for those
particular projects.&lt;/p&gt;
&lt;p&gt;This transition leaves several configuration options redundant, in particular
the following will all be deprecated once unified limits is on by default:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.instances&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.cores&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.ram&lt;/span&gt;&lt;/code&gt;: deprecate all these as
the limit now comes from keystone for unified limits, which will default to
unlimited if there is no limit in keystone.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; will be kept, and will be used in the same
way with unified limits to avoid races when multiple instances are built at
the same time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Ideally we would not add any more proxy APIs, however, operators pushed back
at the Train Forum session, requesting that their tooling continue to work
across the transition. No operators reported using limits other than the
instances, cores and ram limits.&lt;/p&gt;
&lt;p&gt;We could implement hierarchical quotas in isolation, and not adopt unified
limits.&lt;/p&gt;
&lt;p&gt;We could limit the types of resources we limit, but it will be hard to
transition to supporting different kinds of resource limits in a clear
and interoperable way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See upgrades, no changes in Victora due to having old and new quota systems
side by side. Once we remove the old quota system, we could drop all the
quota related DB tables.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt; Nova will proxy the
requests to Keystone’s unified limits API, where possible. The aim will be to
keep horizon functioning correctly during the transition.&lt;/p&gt;
&lt;p&gt;Once using unified limits, operators should move to using Keystone’s
unified limit APIs to set and query limits. Usage information should be
queried via Placement and the Servers API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The removal of quota rechecks for some limits slightly reduces the protection
provided, but really it encourages the proper implementation of API
rate limiting as replacement protection.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Quota errors with unified limits will use the standard and consistent error
messages from oslo.limit after this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;It is possible to have more complicated quota counts with hierarchical
quotas, but the implementation of that is delegated to oslo.limit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;There are several tools to help ease the transition to unified limits noted
above. Although it is expected that use of the feature will help inform the
end direction.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;There will now be two limit system to maintain for a few cycles during the
transition. But this avoids the long term need to maintain complicated
hierarchical limit code, which still getting the advantages, such as being able
to tidy up API policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;To get the best experience, operators need to start using the unified limits
API via Keystone. Users should start querying usage from Placement.&lt;/p&gt;
&lt;p&gt;The transition between the existing quota system and unified limits is
detailed in the proposed solution section.&lt;/p&gt;
&lt;p&gt;It is expected that oslo.limit will limit versions of Keystone that can be
used to Queens and newer, which is not expected to affect most users.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add calls to oslo_limits, guarded by config to enable it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move quota APIs to proxy to Keystone when unified limit quotas enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tools to migrate default and tenant limits from Nova into Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade checks to ensure above tooling is used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keystone manage commands to add limits when keystone API not available&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Grenade test that runs the migration of quota settings (after adding some
quotas).&lt;/p&gt;
&lt;p&gt;Functional tests to ensure quotas are enforced based on unified limits
correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Building on the work to document quota usage from placement, we should
describe how the new system operates. The admin guide needs to detail
how to smoothly migrate to unified limits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 15 Feb 2022 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 15 Feb 2022 00:00:00 </pubDate></item><item><title>Guest CPU selection with hypervisor consideration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/cpu-selection-with-hypervisor-consideration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cpu-selection-with-hypervisor-consideration"&gt;https://blueprints.launchpad.net/nova/+spec/cpu-selection-with-hypervisor-consideration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make Nova’s guest CPU selection approach more effective and reliable by
introducing two new QEMU- and libvirt-based CPU configuration APIs:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt;.  These new
APIs are more “hypervisor-literate” compared to the existing libvirt
APIs that Nova uses.  As in, the new APIs take into account what the
“host hypervisor” (meaning: KVM, QEMU, and what libvirt knows about the
host) is capable of.&lt;/p&gt;
&lt;p&gt;Taking advantage of these newer APIs will allow Nova to make more
well-informed decisions when determining CPU models that are compatible
across different hosts.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current guest CPU config libvirt APIs that Nova uses,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt;, are “not very useful” (quoting
the cover letter &lt;a class="footnote-reference brackets" href="#id5" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; of the libvirt patch series that introduced the
newer APIs), because they don’t consider the capabilities of the “host
hypervisor” (KVM, QEMU and details libvirt knows about the host).  More
concretely, with the existing APIs, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt;, there is no way to ask if a given CPU model plus CPU
flags combination is supported by KVM and a specific QEMU binary on the
host.&lt;/p&gt;
&lt;p&gt;For example, today operators have to be careful about how they configure
the libvirt driver with regard to &lt;cite&gt;cpu_model&lt;/cite&gt; and
&lt;cite&gt;cpu_model_extra_flags&lt;/cite&gt;, because the wrong combination (e.g. an invalid
CPU flag that is not supported by the host hypervisor) can lead to an
instance failing to spawn.  I.e. operators have to manually validate the
extra CPU flags they’re supplying to Nova are actually supported by the
given compute host.&lt;/p&gt;
&lt;p&gt;This spec will allow Nova &lt;a class="footnote-reference brackets" href="#id6" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to do fine-grained validation of a given
CPU model plus CPU flags against a specific QEMU binary (and KVM) to
allow well-informed guest CPU configuration decisions.  And taking
advantage of the said two new libvirt APIs will also allow computing a
more accurate baseline guest CPU that permits live migration across
several compute nodes.  And provides a clearer picture of what CPU
features are required to get mitigations from Meltdown and Spectre.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;By taking advantage of the two CPU configuration APIs,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt;, Nova will
now be able to make meaningful decisions when determining guest CPU
models and their features:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;While determining guest CPU models, Nova can take into account
several other aspects, e.g. the type of virtualization (pure
emulation vs. hardware-accelerated), QEMU binary’s capabilities,
guest machine type, and CPU architcture to construct a
better-informed guest CPU.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova will be able to do more fine-grained validation of CPU models and
flags, i.e. answer questions like: “Is the combination of Intel’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IvyBridge&lt;/span&gt;&lt;/code&gt; CPU model plus the CPU flags &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pcid&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ssbd&lt;/span&gt;&lt;/code&gt;
supported by the host hypervisor?”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Armed with the above two points, Nova will also be positioned to
better report more accurate CPU traits.  (I.e. improve the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_cpu_traits()&lt;/span&gt;&lt;/code&gt; method.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operators can get a more accurate view on what guest CPU models and
features their guests can realistically expect.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Make Nova’s CPU selection strategy more effective by taking advantage of
the two new libvirt APIs: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.  These APIs provide more useful ways to
determine compatible models among CPU variants, and elimiates bugs in
the older CPU config libvirt APIs along the way.&lt;/p&gt;
&lt;p&gt;With this change, the libvirt driver will automatically validate if a
certain combination of CPU model + flags can work on a given compute
host — e.g. Nova will now be able to answer: “Is this combination of
‘IvyBridge’ plus CPU flags ‘pcid’ &amp;amp; ‘pdpe1gb’ supported by KVM, QEMU and
libvirt on the host?”.  And, if the given combination of CPU model plus
flags are invalid, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; service will refuse to start,
with an actionable log message.&lt;/p&gt;
&lt;p&gt;This will let the operator set the CPU model plus flags, and let Nova
handle the validation.&lt;/p&gt;
&lt;p&gt;A quick description of the two APIs:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Purpose: This API computes the most feature-rich “baseline” CPU (which
includes CPU model plus additional features) that is (a) compatible with
all given host CPUs (as described in an XML document), so that one can
live migrate across the said hosts; and (b) is supported by the host
hypervisor.  It is a more useful version of the older &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselinCPU()&lt;/span&gt;&lt;/code&gt;,
which does not consider any hypervisor capabilities when computing the
baseline CPU.&lt;/p&gt;
&lt;p&gt;A comparison of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; APIs,
in terms of what parameters they take into account:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+-----------+--------------------+-----------------------------+
|           | baselineCPU()      | baselineHypervisorCPU()     |
+-----------+--------------------+-----------------------------+
|           | XML document       | XML document describing     |
|           | describing one     | one or more host CPUs       |
|           | or more host CPUs  |                             |
|           +--------------------+-----------------------------+
|           |                    | path to the QEMU binary     |
|           |                    +-----------------------------+
|Parameters |                    | the type of virtualization  |
|           |                    | (e.g. KVM, QEMU)            |
|           |                    +-----------------------------+
|           |                    | guest machine type          |
|           |                    +-----------------------------+
|           |                    | CPU architecture            |
+-----------+--------------------+-----------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Purpose: This API compares a given CPU description with the CPU
capabilities the host hypervisor is able to provide.  It is a more
useful version of the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt;, which compares the CPU
definition with the host CPU without considering any specific hypervisor
and its abilities.&lt;/p&gt;
&lt;p&gt;A comparison of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt; APIs, in
terms of what parameters they take into account:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+-----------+--------------------+-----------------------------+
|           | compareCPU()       | compareHypervisorCPU()      |
+-----------+--------------------+-----------------------------+
|           | XML describing the | XML describing the CPU      |
|           | CPU to be compared | to be compared              |
|           +--------------------+-----------------------------+
|           |                    | path to the QEMU binary     |
|           |                    +-----------------------------+
|Parameters |                    | the type of virtualization  |
|           |                    | (e.g. KVM, QEMU)            |
|           |                    +-----------------------------+
|           |                    | guest machine type          |
|           |                    +-----------------------------+
|           |                    | CPU architecture            |
+-----------+--------------------+-----------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;By making Nova use the above two APIs, it can now do more advanced
validation of CPU model plus flags compatibility, which ensures an
instance cannot be launched with CPU features that don’t exist in the
host CPU.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could just “stay put” and keep chugging along with the existing older
libvirt APIs, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But that would be doing a disservice to our users, as we have more
reliable APIs that provide a more well-informed guest CPU configuration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This implicitly improves security – as in, with these new APIs, you
should be able to get a better sense of what CPU features are required
to get mitigations from Meltdown and Spectre.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The following libvirt and QEMU versions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt;: QEMU &amp;gt;= 2.9, libvirt &amp;gt;= 4.4.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;s390x&lt;/span&gt;&lt;/code&gt;: QEMU &amp;gt;= 2.9, libvirt work is actively in progress
upstream &lt;a class="footnote-reference brackets" href="#id8" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt;, users should have the minimum-required verisons of
libvirt and QEMU to be 4.4.0 and 2.9, respectively.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;chengsheng&amp;gt;
&amp;lt;kashyapc&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce a Nova wrapper method, baseline_hypervisor_cpu(), for
libvirt’s baselineHypervisorCPU() API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a Nova wrapper method, compare_hypervisor_cpu(), for
libvirt’s compareHypervisorCPU() API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rework the _get_guest_cpu_model_config() method in the libvirt
driver to take advantage of the fine-grained validation of CPU model
plus features (against a given QEMU binary), if available on the given
compute host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rewrite the _compare_cpu() method’s the logic in the libvirt driver to
take advantage of compareHypervisorCPU().  (While at it, rename it to
_compare_hypervisor_cpu().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the check_can_live_migrate_destination() method in the libvirt
driver to use the newer wrapper API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the get_capabilities() method in nova/virt/libvirt/host.py to
take advantage of baseline_hypervisor_cpu(), if available on the given
compute host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This can be done separately, but noting for completeness’ sake: Update
_get_cpu_traits() method to use baselineHypervisorCPU().  (Support for
s390x shouldn’t be a blocker to get started on this.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This is not a strict dependency, but as noted earlier, support for s390x
for libvirt’s compareHypervisorCPU() and baselineHypervisorCPU() is
still in progress upstream.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce “fake libvirt” methods for baselineHypervisorCPU() and
compareHypervisorCPU() APIs with minimum-required functionanlity
(because duplicating libvirt’s logic is complicated and doesn’t add
much value to replicate it).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Potentially a couple of functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Consider adding a section in the Nova admin guide on how the newer APIs
allow more reliable guest CPU configuration.  Also note explicitly that
we recommend to stick to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host-model&lt;/span&gt;&lt;/code&gt;, which is the the default CPU
mode for the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;“New CPU related APIs”
– &lt;a class="reference external" href="https://www.redhat.com/archives/libvir-list/2018-May/msg01204.html"&gt;https://www.redhat.com/archives/libvir-list/2018-May/msg01204.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;“[RFE] Fine-grained API to validate if a given CPU model and flags
are supported by QEMU / KVM”
– &lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1559832"&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1559832&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Refer to slide-28 here:
&lt;a class="reference external" href="https://kashyapc.fedorapeople.org/Effective-Virtual-CPU-Configuration-in-Nova-Berlin2018.pdf"&gt;https://kashyapc.fedorapeople.org/Effective-Virtual-CPU-Configuration-in-Nova-Berlin2018.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;libvirt work for s390x:
&lt;a class="reference external" href="https://www.redhat.com/archives/libvir-list/2019-January/msg00310.html"&gt;https://www.redhat.com/archives/libvir-list/2019-January/msg00310.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 10 Jan 2022 00:00:00 </pubDate></item><item><title>Per Process Healthcheck endpoints</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/per-process-healthchecks.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks"&gt;https://blueprints.launchpad.net/nova/+spec/per-process-healthchecks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In many modern deployment frameworks, there is an expectation that
an application can expose a health-check endpoint so that the binary
status can be monitored. Nova currently does not provide a native way
to inspect the health of its binaries which doesn’t help cloud monitoring
and maintenance. While limited support exists for health checks via
oslo middleware for our WSGI based API binaries, this blueprint seeks
to expose a local HTTP health-check endpoint to address this
feature gap consistently for all nova components.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;To monitor the health of a nova service today requires experience to
develop and implement a series of external heuristics to infer the state
of the service binaries.&lt;/p&gt;
&lt;p&gt;This can be as simple as checking the service status for those with heartbeats
or can comprise monitoring log output via a watchdog and restarting
the service if no output is detected after a protracted period.
Processing the logs for known error messages and executing a remediation script
or other methods that are easy to do incorrectly are also common.&lt;/p&gt;
&lt;p&gt;This is also quite unfriendly to new nova users who have not gained enough
experience with operating nova to know what warning signs they should look
for such as inability to connect to the message bus. Nova developers however
do know what some of the important health indicators are and can expose
those as a local health-check endpoint that operators can use instead.&lt;/p&gt;
&lt;p&gt;The existing oslo middleware does not address this problem statement because:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;it can only be used by the API and metadata binaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the middleware does not tell you the service is alive if its hosted by a
WSGI server like apache since the middleware is executed independently from
the WSGI application. i.e. the middleware can pass while the nova-api can’t
connect to the db and is otherwise broken.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the oslo middleware in detailed mode leaks info about the host python
kernel, python version and hostname which can be used to determine in the
host is vulnerable to CVEs which means it should never be exposed to the
Internet. e.g.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Linux-5.15.2-xanmod1-tt-x86_64-with-glibc2.2.5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;python_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3.8.12 (default, Aug 30 2021, 16:42:10) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[GCC 10.3.0]'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want a simple REST endpoint I can consume to know
if a nova process is healthy.&lt;/p&gt;
&lt;p&gt;As an operator I want this health check to not impact the performance of the
service so it can be queried frequently at short intervals.&lt;/p&gt;
&lt;p&gt;As a deployment tool implementer, I want the health check to be local with no
dependencies on other hosts or services to function so I can integrate it with
service managers such as systemd or container runtime like docker&lt;/p&gt;
&lt;p&gt;As a packager, I would like using the health check endpoint to not require
special clients or packages to consume them. cURL, socat, or netcat should be
all that is required to connect to the health check and retrieve the service
status.&lt;/p&gt;
&lt;p&gt;As an operator I would like to be able to use health-check of the nova API and
metadata services to manage the membership of endpoints in my load-balancer
or reverse proxy automatically.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="definitions"&gt;
&lt;h3&gt;Definitions&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TTL&lt;/span&gt;&lt;/code&gt;: The time interval for which a health check item is valid.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;: all health indicators are passing and there TTLs have not expired.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt;: any health indicator has an expired TTL or where there is
a partial transient failure.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;: any health indicator is reporting an error or all TTLs are expired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="warn-vs-fail"&gt;
&lt;h3&gt;warn vs fail&lt;/h3&gt;
&lt;p&gt;In general if any of the health check indicators are failing then the service
should be reported as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; however if the specific error condition is
recoverable or only a partial failure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state can and should be
used.&lt;/p&gt;
&lt;p&gt;An example of this is a service that has lost a connection to the message bus,
when the connection is lost it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state, if the first
attempt to reconnect fails it should go to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; status. Transient
failure should be considered warning but persistent errors should be escalated
to failures.&lt;/p&gt;
&lt;p&gt;In many cases external management systems will treat &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; as
equivalent and raise an alarm or restart the service. While this spec does
not specify how you should recover from a degraded state it is
important to include a human readable description of why the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; state was entered.&lt;/p&gt;
&lt;p&gt;Services in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; state are still considered healthy in most case but
they may be about to fail soon or be partially degraded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-changes"&gt;
&lt;h3&gt;code changes&lt;/h3&gt;
&lt;p&gt;A new top-level nova health check module will be created to encapsulate the
common code and data structure required to implement this feature.&lt;/p&gt;
&lt;p&gt;A new health check manager class will be introduced which will maintain the
health-check state and all functions related to retrieving, updating and
summarizing that state.&lt;/p&gt;
&lt;p&gt;The health check manager will be responsible for creating the health check
endpoint when it is enabled in the nova.conf and exposing the health check
over HTTP.&lt;/p&gt;
&lt;p&gt;The initial implementation will support HTTP over TCP with optional support for
UNIX domain sockets as a more secure alternative to be added later.
The HTTP endpoint in both cases will be unauthenticated and the response will
be in JSON format.&lt;/p&gt;
&lt;p&gt;A new HealthcheckStausItem data class will be introduced to store and
individual health check data-point. The HealtcheckSTatusItem will contain
the name of the health check, its status, the time it was recorded,
and an optional output string that should be populated if the
status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A new decorator will be introduced that will automatically retrieve the
reference to the healthcheck manager from the nova context object and update
the result based on if the function decorated raises an exception or not.
The exception list and healthcheck item name will be specifiable.&lt;/p&gt;
&lt;p&gt;The decorator will accept the name of the health check as a positional argument
and include the exception message as the output of the health check on failure.
Note that the decorator will only support the pass or fail status for
simplicity, where warn is appropriate a manual check should be written.
if multiple functions act as indicator of the same capability the same name
should be used.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="nd"&gt;@healthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'database'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SQLAlchemyError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;my_other_db_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default all exceptions will be caught and re-raised by the decorator.&lt;/p&gt;
&lt;p&gt;The new REST health check endpoint exposed by this spec will initially only
support one url path &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt;. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; endpoint will include a
&lt;cite&gt;Cache-Control: max-age=&amp;lt;ttl&amp;gt;&lt;/cite&gt; header as part of its response which can
optionally be consumed by the client.&lt;/p&gt;
&lt;p&gt;The endpoint may also implement a simple incrementing etag at a later date
once the initial implementation is complete if required.
Initially adding an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; is not provided as the response is expected to be
small and cheap to query so etags do not actually provide much benefit form
a performance perspective.&lt;/p&gt;
&lt;p&gt;If implemented the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;etag&lt;/span&gt;&lt;/code&gt; will be incremented whenever the service state
changes and will reset to 0 when the service is restarted.&lt;/p&gt;
&lt;p&gt;Additional url paths may be supported in the future for example to retrieve
the running configuration or trigger the generation of Guru Meditation Reports
or enable debug logging, however any endpoint beyond &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/health&lt;/span&gt;&lt;/code&gt; is out of
scope of this spec. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; is not used for health check response to facilitate
additional paths in the future.&lt;/p&gt;
&lt;section id="example-output"&gt;
&lt;h4&gt;example output&lt;/h4&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"e3c22423-cd7a-47dc-b6e9-e18d1a8b3bdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"contoler-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"contoler-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"API_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="n"&gt;Sevice&lt;/span&gt; &lt;span class="n"&gt;Unavailable&lt;/span&gt;
&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"serviceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0a47dceb-11b1-4d94-8b9c-927d998be320"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-compute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"contoler-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"contoler-1.cloud"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"message_bus"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:02:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"hypervisor"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
             &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2021-12-17T16:05:55+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s2"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Libvirt Error: ..."&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of maintaining the state of the process in a data structure and
returning the cached state we could implement the health check as a series of
active probes such as checking the DB schema version to ensure we can access
it or making a ping RPC call to the cell conductor or our own services RPC
endpoint.&lt;/p&gt;
&lt;p&gt;While this approach has some advantages it will have a negative performance
impact if the health-check is queried frequently or in a large deployment where
infrequent queries may still degrade the DB and message bus performance due to
the scale of the deployment.&lt;/p&gt;
&lt;p&gt;This spec initially suggested using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OK&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Degraded&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Faulty&lt;/span&gt;&lt;/code&gt; as the
values for the status field. these were updated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pass&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; to align with the draft IETF RFC for health check response format for
http APIs &lt;a class="reference external" href="https://tools.ietf.org/id/draft-inadarei-api-health-check-06.html"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The nova context object will be extended to store a reference to the
health check manager.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While this change will expose a new REST API endpoint it will not be
part of the existing nova API.&lt;/p&gt;
&lt;p&gt;In the nova API the /health check route will not initially be used to allow
those that already enable the oslo middleware to continue to do so.
In a future release nova reserves the right to add a /health check endpoint
that may or may not correspond to the response format defined in oslo.
A translation between the oslo response format and the health check module
may be provided in the future but it is out of the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The new health check endpoint will be disabled by default.
When enabled it will not provide any authentication or explicit access control.
The documentation will detail that when enabled the TCP endpoint should be
bound to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;localhost&lt;/span&gt;&lt;/code&gt; and that file system permission should be used to secure
the UNIX socket.&lt;/p&gt;
&lt;p&gt;The TCP configuration option will not prevent you from binding it to a
routable IP if the operator chooses to do so. The intent is that the data
contained in the endpoint will be non-privileged however it may contain
Hostnames/FQDNs or other infrastructure information such as service UUIDs so
it should not be accessible from the Internet.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;While the health checks will use the ability to send notification as an input
to determine the health of the system, this spec will not introduce any new
notifications as such it will not impact the Notification subsystem in nova.
New notifications are not added as this would incur a performance overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;At present, it is not planned to extend the nova client or the unified client
to query the new endpoint. CURL, SOCAT, or any other UNIX socket or TCP HTTP
client can be used to invoke the endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;We expect there to be little or no performance impact as we will be taking a
minimally invasive approach to add health indicators to key functions
which will be cached in memory. While this will slightly increase memory usage
there is no expected impact on system performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A  new config section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;healthcheck&lt;/span&gt;&lt;/code&gt;  will be added in the nova.conf&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uri&lt;/span&gt;&lt;/code&gt; config option will be introduced to enable the health check
functionality. The config option will be a string opt that supports a
comma-separated list of URIs with the following format&lt;/p&gt;
&lt;p&gt;uri=&amp;lt;scheme&amp;gt;://[host:port|path],&amp;lt;scheme&amp;gt;://[host:port|path]&lt;/p&gt;
&lt;p&gt;e.g.
[healthcheck]
uri=tcp://localhost:424242&lt;/p&gt;
&lt;p&gt;[healthcheck]
uri=unix:///run/nova/nova-compute.sock&lt;/p&gt;
&lt;p&gt;[healthcheck]
uri=tcp://localhost:424242,unix:///run/nova/nova-compute.sock&lt;/p&gt;
&lt;p&gt;The URI should be limited to the following charterers &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[a-zA-Z0-9_-]&lt;/span&gt;&lt;/code&gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;,&lt;/span&gt;&lt;/code&gt; is reserved as a separation charterer, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; may only be used in ipv4
addresses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt; is reserved for port separation unless the address is an ipv6
address. ipv6 addresses must be enclosed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[&lt;/span&gt;&lt;/code&gt; and  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;]&lt;/span&gt;&lt;/code&gt;.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/&lt;/span&gt;&lt;/code&gt; may be used with the UNIX protocol however relative paths are not
supported.
These constraints and the parsing of the URI will be enforced and provided by
the rfc3986 lib &lt;a class="reference external" href="https://pypi.org/project/rfc3986/"&gt;https://pypi.org/project/rfc3986/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt; intOpt will be added with a default value of 300 seconds.
If set to 0 the time to live of a health check items will be infinite.
If the TTL expires the state will be considered unknown and
the healthcheck item will be discarded.&lt;/p&gt;
&lt;p&gt;A cache_contol intOpt will be provide to set the max-age value in the
cache_contol header. By default it will have the same max-age as the ttl
config option. setting this to 0 will disable the reporting of the header.
setting this to -1 will report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Cache-Control:&lt;/span&gt; &lt;span class="pre"&gt;no-cache&lt;/span&gt;&lt;/code&gt;
any other positive integer value will be used as the max-age.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers should be aware of the new decorator and consider if it should be
added to more functions if that function is an indicator of the system’s
health. Failures due to interactions with external system such as neutron port
binding external events should be handled with caution. While failure to
receive a port binding event will likely result in the failure to boot a vm it
should not be used as a health indicator for the nova-compute agent. This is
because such a failure may be due to a failure in neutron not nova. As such
other operations such as vm snapshot may be unaffected and the nova compute
service may be otherwise healthy. Any failure to connect to a non OpenStack
service such as the message bus hypervisor or database however should be
treated as a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warn&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fail&lt;/span&gt;&lt;/code&gt; health indicator if it prevents the nova
binary from functioning correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce decorator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend context object to store a reference to health check manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose TCP endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose UNIX socket endpoint support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested entirely with unit and functional tests however,
devstack will be extended to expose the endpoint and use it to determine
if the nova services have started.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The config options will be documented in the config reference
and a release note will be added for the feature.&lt;/p&gt;
&lt;p&gt;A new health check section will be added to the admin docs describing
the current response format and how to enable the feature and its intended
usage. This document should be evolved whenever the format changes or
new functionality is added beyond the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;yoga ptg topic:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415"&gt;https://etherpad.opendev.org/p/r.e70aa851abf8644c29c8abe4bce32b81#L415&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 09 Dec 2021 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-encryption-libvirt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store a symmetric key in the key manager. This
remains a long running piece of technical debt in the encrypted volume
implementation as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; does not directly encrypt data with the provided
key.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID.&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypt these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/ephemeral-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/ephemeral-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Nov 2021 00:00:00 </pubDate></item><item><title>Update userdata</title><link>https://specs.openstack.org/openstack/nova-specs/specs/zed/approved/update-userdata.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/update-userdata"&gt;https://blueprints.launchpad.net/nova/+spec/update-userdata&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It should be possible to update an instance’s user data without
the need to rebuild the corresponding instance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, it is not possible to update an instance’s user data without
rebuilding it.&lt;/p&gt;
&lt;p&gt;Rebuilding takes much more time than just propagating updated user data,
e. g. via cloud-init, and may be unfavorable in production.
Editing a few lines in a cloud config file should not lead to a whole
rebuild of an instance.&lt;/p&gt;
&lt;p&gt;Additionally, other public cloud providers like Azure [1] have the
functionality to update user data for an existing instance, so
end users may expect this to work in Nova as well.&lt;/p&gt;
&lt;p&gt;AWS requires the instance to be powered off [2] before updating user data
and Google also allows updates at any time [3][4].&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;[1] &lt;a class="reference external" href="https://docs.microsoft.com/en-us/azure/virtual-machines/user-data#what-is-user-data"&gt;https://docs.microsoft.com/en-us/azure/virtual-machines/user-data#what-is-user-data&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;[2] &lt;a class="reference external" href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-view-change"&gt;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-view-change&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;[3] &lt;a class="reference external" href="https://cloud.google.com/container-optimized-os/docs/how-to/create-configure-instance#using_cloud-init_with_the_cloud_config_format"&gt;https://cloud.google.com/container-optimized-os/docs/how-to/create-configure-instance#using_cloud-init_with_the_cloud_config_format&lt;/a&gt;&lt;/div&gt;
&lt;div class="line"&gt;[4] &lt;a class="reference external" href="https://cloud.google.com/compute/docs/reference/rest/v1/instances/setMetadata"&gt;https://cloud.google.com/compute/docs/reference/rest/v1/instances/setMetadata&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I want to dynamically reconfigure the time and name servers used
by my instance via user data in order to update theses settings using the
same interface (user data) I initially used to bootstrap the instance.&lt;/p&gt;
&lt;p&gt;As a user with experience at provisioning ephemeral workloads with tools like
cloud-init, I would like to manage my stateful workload via user data and
metadata on each boot. Metadata is used to store my external configuration
while user data is used to perform operations like rejoining a cluster when the
update has been applied.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt; API should accept an additional
parameter named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_data&lt;/span&gt;&lt;/code&gt; to allow updates to the instance’s user data.&lt;/p&gt;
&lt;p&gt;If the parameter is set in the request body, Nova should update the instance’s
user data to the value set in the request parameter (if the input is valid,
i. e. not longer than 65535 bytes).&lt;/p&gt;
&lt;p&gt;In case the instance uses a config drive, the above method should not be
allowed and rejected with a clear response message and 409 (conflict) status
code. Instead, the user data can be updated via a hard reboot, i. e. via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; API, with an additional parameter similar
to the above method. The config drive will be rebuilt automatically on a hard
reboot, containing the updated user data.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt; API is extended by the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_data&lt;/span&gt;&lt;/code&gt; parameter. This is added in a new microversion.
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; API is updated accordingly.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id}&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"user_data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"reboot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HARD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"user_data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above is an example of a minimal request which changes the user data
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The option to update user data with openstackclient is required:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;set&lt;/span&gt; &lt;span class="pre"&gt;--user-data&lt;/span&gt; &lt;span class="pre"&gt;{data}&lt;/span&gt; &lt;span class="pre"&gt;{server_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;An option to update user data on a hard reboot should be added as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jhartkopf&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement API changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstackclient needs to be updated to implement this change&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add unit tests (positive and negative)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functional test (API samples)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API reference needs to be updated to reflect the new microversion’s
feature.&lt;/p&gt;
&lt;p&gt;In addition, make clear that user data is mutable but also that it does not
replace proper config management.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Zed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 03 Nov 2021 00:00:00 </pubDate></item><item><title>Allow Manila shares to be directly attached to an instance when using libvirt</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/libvirt-virtiofs-attach-manila-shares.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Manila is the OpenStack Shared Filesystems service. This spec will outline API,
database, compute and libvirt driver changes required in Nova to allow the
shares provided by Manila to be associated with and attached to instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present users must manually connect to and mount shares provided by Manila
within their instances. As a result of this Manila has to expose details of
the backend storage infrastructure to the user and allow the datapath to flow
over tenant addressable networks into the users instances.&lt;/p&gt;
&lt;p&gt;An alternative to this is for Nova to mount these shares on the underlying
compute host and then pass through the provided filesystems to the instance,
keeping the datapath outside of any tenant addressable network and without
exposing details about the backend storage infrastructure.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to attach Manila shares directly to my instance and have a
simple interface with which to mount them within the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to detach a directly attached Manila share from my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to track the Manila shares attached to my instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want the Manila datapath to be separate to any tenant
accessible networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I don’t want to expose details of my storage infrastructure to
users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This initial implementation will only provide support for attaching a share to
and later detaching a share from an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; instance. The ability
to express attachments during the initial creation of an instance will not be
covered by this spec.&lt;/p&gt;
&lt;p&gt;Support for move operations once a share is attached will also not
be covered by this spec, any requests to shelve, evacuate, resize, cold migrate
or live migrate an instance with a share attached will be rejected for the time
being.&lt;/p&gt;
&lt;p&gt;A new server &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion. This
will list current shares, show their details and allow a share to be
attached or detached.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table and associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt;
versioned objects will be introduced to capture details of the share
attachment. A base ShareMapping versioned object will be provided from which
virt driver and backend share specific objects can be derived providing
specific share attach and detach implementations.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;One thing to note here is that no Manila state will be stored within Nova
aside from export details used to initially attach the share. These details
later being used when detaching the share. If the share is then reattached
Nova will request fresh export details from Manila and store these in a
new share attachment within Nova.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The libvirt driver will be extended to support the above with initial support
for cold attach and detach. Future work will aim to add live attach and detach
once &lt;a class="reference external" href="https://listman.redhat.com/archives/libvir-list/2021-October/msg00097.html"&gt;support lands in libvirt itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This initial libvirt support will target the basic NFS and slightly more
complex CephFS backends within Manila. Shares will be mapped through to the
underlying libvirt domains using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt;. This will require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QEMU&lt;/span&gt;&lt;/code&gt;
&amp;gt;=5.0 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; &amp;gt;= 6.2 on the compute host and a kernel version of &amp;gt;= 5.4
within the instance guest OS.&lt;/p&gt;
&lt;p&gt;Additionally this initial implementation will require that the associated
instances use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/file-backed-memory.html"&gt;file backed memory&lt;/a&gt; or &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;huge pages&lt;/a&gt;. This is a requirement
of &lt;a class="reference external" href="https://virtio-fs.gitlab.io/"&gt;virtio-fs&lt;/a&gt; as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtiofsd&lt;/span&gt;&lt;/code&gt; service uses the &lt;a class="reference external" href="https://qemu-project.gitlab.io/qemu/interop/vhost-user.html"&gt;vhost-user&lt;/a&gt; protocol
to communicate directly with the underlying guest.&lt;/p&gt;
&lt;p&gt;Two new compute compatibility traits will be introduced to model an individual
compute’s support for virtio-fs and file backed memory.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STORAGE_VIRTIO_FS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_MEM_BACKING_FILE&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These will then be used along with the flavor and image metadata associated
with the instance to ensure the above requirements are met during a request to
attach a share.&lt;/p&gt;
&lt;p&gt;Future work will look into dropping this requirement and introducing a more
robust way of allowing access to the underlying guest memory via flavor extra
specs and image properties but that is left out of scope for this spec.&lt;/p&gt;
&lt;p&gt;Users will be able to mount the attached shares using a mount tag, this is
either the share UUID from Manila or a string provided by the user with their
request to attach the share.&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;user@instance&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;virtiofs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/mnt/mount/path
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A previously discussed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-share&lt;/span&gt;&lt;/code&gt; library will not be created with this
initial implementation but could be in the future if the logic required to
mount and track shares on the underlying host is also required by other
projects. For the time being &lt;a class="reference external" href="https://github.com/openstack/nova/blob/8f250f50446ca2d7aa84609d5144088aa4cded78/nova/virt/libvirt/volume/mount.py#L152-L174"&gt;existing code within the libvirt driver&lt;/a&gt; used
to track filesystem host mounts used by volumes hosted on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remoteFS&lt;/span&gt;&lt;/code&gt; based
storage (such as NFS, SMB etc) will be reused as much as possible.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The only alternative is to continue with the current situation where users must
mount the shares within their instances manually. The downside being that these
instances must have access to the storage network used by the Manila backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new server level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shares&lt;/span&gt;&lt;/code&gt; API will be introduced under a new microversion
with the following methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;List all shares attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"shares"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"48c16a1a-183f-4052-9dac-0e4fc1e498ad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attached"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attached"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Show details of a specific share attached to an instance.&lt;/p&gt;
&lt;p&gt;Return Code(s): 200,400,401,403,404&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attached"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Admins will be able to see details of the attachment id and export location
stored within Nova:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"715335c1-7a00-4dfe-82df-9dc2a67bd8bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attached"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"export_location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.com/nfs_mount,foo=bar"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attach a share to an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;This is an asynchronous API, callers will need to poll one of the above GET
methods to determine when the attachment is complete.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;p&gt;Request body:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; will be an optional request parameter, when not provided it
will be the shareId as always provided in the request.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"shareId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attaching"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e8debdc0-447a-4376-a10a-4cd9122d7986"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DELETE&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/shares/{shareId}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detach a share from an instance.&lt;/p&gt;
&lt;p&gt;Prerequisite(s): Instance much be in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTOFF&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;Return Code(s): 202,400,401,403,404,409&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_mapping&lt;/span&gt;&lt;/code&gt; database table will be introduced.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; - Unique UUID to identify the particular share attachment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_uuid&lt;/span&gt;&lt;/code&gt; - The UUID of the instance the share will be attached to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;share_id&lt;/span&gt;&lt;/code&gt; - The UUID of the share in Manila&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; - The status of the share attachment within Nova.
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detached&lt;/span&gt;&lt;/code&gt;
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attaching&lt;/span&gt;&lt;/code&gt;
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attached&lt;/span&gt;&lt;/code&gt;
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detaching&lt;/span&gt;&lt;/code&gt;
- &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt; - The device tag to be used by users to mount the share within&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;the instance&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; - The export location used to attach the share to the&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;underlying host.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; versioned object will be introduced to encapsulate
the above database entries and to be used as the parent class of specific virt
driver implementations.&lt;/p&gt;
&lt;p&gt;This base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMapping&lt;/span&gt;&lt;/code&gt; object will provide stub &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;detach&lt;/span&gt;&lt;/code&gt;
methods that will need to be implemented by any child objects.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirt&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtNFS&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ShareMappingLibvirtCephFS&lt;/span&gt;&lt;/code&gt; objects will be introduced as part of the libvirt
implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should improve the security model of using Manila by removing the datapath
from tenant networks while also removing the need for users to know details of
the underlying storage environment.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;export_location&lt;/span&gt;&lt;/code&gt; JSON blob returned by Manila and used to attach the
share to the underlying host should not be logged by Nova and only accessible
by default through the API by admins.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;New notifications will be added to represent the attaching and detaching of a
share to an instance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will need to mount the shares within their guestOS using the returned
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Through the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vhost-user&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; should have near local
(mounted) file system performance within the guestOS.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new compute service version and compatibility traits will be introduced to
ensure both the compute service and underlying virt stack are new enough to
support attaching a share via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-fs&lt;/span&gt;&lt;/code&gt; before the request is accepted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new compatibility traits within os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support within the libvirt driver for cold attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new shares API and microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional libvirt driver and API tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive admin and user documentation will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 08 Oct 2021 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;p&gt;Note that this spec will only cover the high level changes to the API and
compute layers, implementation within specific virt drivers is left for
separate specs.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to
if an image is encrypted at rest within the Glance service. They only relate
to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-compute-ephemeral-encryption-compatibility-traits"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/h3&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility traits was introduced
during &lt;a class="reference external" href="https://review.opendev.org/c/openstack/os-traits/+/759878"&gt;Wallaby&lt;/a&gt; and will be reported by virt drivers to indicate overall
support for ephemeral storage encryption using this new approach. This trait
will always be used by pre-filter outlined in the following section when
ephemeral encryption has been requested, regardless of any format being
specified in the request, allowing the compute that eventually handles the
request to select a format it supports using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt; configurable.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits were also
added to os-traits during Wallaby and will be reported by virt drivers to
indicate support for specific ephemeral storage encryption formats. For
example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Store and allow libvirt instance device buses and models to be updated</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/libvirt-device-bus-model-update.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-device-bus-model-update"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-device-bus-model-update&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;QEMU support for device buses and models can come and go dependent on the
underlying instance machine type &lt;em&gt;and&lt;/em&gt; QEMU version used within an environment.
The defaults provided by libosinfo and currently hardcoded in to the libvirt
driver are also not persisted by each instance at present.&lt;/p&gt;
&lt;p&gt;This spec aims to outline a basic set of nova-manage commands to allow
operators to move instances between specific device bus and model types without
requiring a rebuild.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present device bus and model types defined as image properties associated
with an instance are always used when launching instances with the libvirt
driver. When these types are not defined as image properties their values
either come from libosinfo or those directly hardcoded into the libvirt driver.&lt;/p&gt;
&lt;p&gt;Support for each device bus and model is dependent on the machine type used
&lt;em&gt;and&lt;/em&gt; version of QEMU available on the underlying compute host.&lt;/p&gt;
&lt;p&gt;As such any changes to the machine type of an instance or version of QEMU on a
host might suddenly invalidate the now stashed device bus or model image
properties with no way of updating outside of a complete instance rebuild
against a new image defining new image properties.&lt;/p&gt;
&lt;p&gt;Additionally any changes to the defaults provided by libosinfo or the libvirt
driver could result in unforeseen changes to existing instances. This has been
encountered in the past as libosinfo assumes that libvirt domain definitions
are static when OpenStack Nova specifically rewrites and redefines these
domains during a hard reboot or migration allowing changes to possibly occur.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want the device buses and models used by my instance to remain
stable for as long as possible and not be changed by new defaults in
libosinfo or the OpenStack Nova libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to change the device bus or model of an instance
&lt;em&gt;without&lt;/em&gt; forcing users to fully rebuild the instance in order to accommodate
changing machine types or QEMU deprecations for certain types.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="register-existing-device-buses-and-models-within-system-metadata"&gt;
&lt;h3&gt;Register existing device buses and models within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt; we first want to ensure the current device bus and
model types associated with an instance are stashed ensuring they remain
stable during the lifetime of the instance. This already happens when these
buses or models are defined by image properties so we only need to capture
their value when these are not defined at either service startup or instance
creation time.&lt;/p&gt;
&lt;p&gt;The following list of image properties outline the list of device buses and
models this spec will aim to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_floppy_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_rescue_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_input_bus&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pointer_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_rng_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_scsi_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_video_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vif_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="provide-nova-manage-commands-to-update-existing-device-buses-and-models"&gt;
&lt;h3&gt;Provide nova-manage commands to update existing device buses and models&lt;/h3&gt;
&lt;p&gt;With the bus and model types stored we can now provide commands to operators to
inspect and update only the list of allowed image properties above:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;image-property&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt; &lt;span class="pre"&gt;$instance&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Will list the stashed image properties of an instance.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;image-property&lt;/span&gt; &lt;span class="pre"&gt;set&lt;/span&gt; &lt;span class="pre"&gt;--property&lt;/span&gt; &lt;span class="pre"&gt;hw_disk_bus=scsi&lt;/span&gt; &lt;span class="pre"&gt;--property&lt;/span&gt;
&lt;span class="pre"&gt;hw_scsi_model=virtio-scsi&lt;/span&gt; &lt;span class="pre"&gt;$instance&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Will update image properties of an instance, only accepting the previously
defined list of image properties for the time being.&lt;/p&gt;
&lt;section id="prerequisites"&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;The following prerequisites apply when attempting to update the image
properties of an instance:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The instance must be in a STOPPED, SHELVED or SHELVED_OFFLOADED vm_sate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The provided type will be validated against the corresponding versioned
object fields for the bus or model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once updated the user or admin can power on or unshelve the instance, causing
the underlying libvirt domain to be redefined using the new bus or model type.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None, other than providing a generic API to allow stashed image properties to
be updated by users over time without requiring a rebuild but that’s out of
scope for this basic nova-manage command spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users should now find that the device bus and models used by their instances
remain stable throughout their lifetime unless a move is forced upon them
by the operator, QEMU support deprecations etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Stashing these values will incur a slight overhead at compute service start
time when using the libvirt driver and additionally when spawning new
instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators should have more control over when and how they move users to
different machine types and versions of QEMU.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Register existing device buses and models within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide nova-manage commands to update existing device buses and models&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Extensive unit and functional tests will be written to validate this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operator/admin facing documentation will be written outling the usecase for
these commands as well as the normal documentation for the commands themselves.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Add attachmentId to responses of the os-volume_attachments API</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/add-attachmentid-to-responses-of-the-os-volume-attachments-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/add-attachmentid-to-responses-of-the-os-volume-attachments-api"&gt;https://blueprints.launchpad.net/nova/+spec/add-attachmentid-to-responses-of-the-os-volume-attachments-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec aims to outline the use case for adding volume attachment ids to the
responses of Nova’s &lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=#servers-with-volume-attachments-servers-os-volume-attachments"&gt;os-volume_attachments APIs&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When using the Cinder volume attachments API to attach a volume to an
instance Nova will record the id of the Cinder volume attachment within the
block device mapping table. However this is not exposed at present through
Nova’s os-volume_attachments APIs and is only visible through Cinders
attachments API or direct queries to Nova’s database.&lt;/p&gt;
&lt;p&gt;For example, using the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-train"&gt;v2.79 mircoversion&lt;/a&gt; GETs against the API provide the
following responses:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/os-volume_attachments&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"227cc671-f30b-4488-96fd-7d0bf13648d8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d5e4ae35-ac0e-4311-a8c5-0ee863e951d9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"227cc671-f30b-4488-96fd-7d0bf13648d8"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d5e4ae35-ac0e-4311-a8c5-0ee863e951d9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/os-volume_attachments/{volume_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2aad99d3-7aa4-41e9-b4e6-3f960b115d68"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; returned above responses is the id of Nova’s block device
mapping record and not that of the volume attachment in Cinder.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This renders the API useless in most volume attach troubleshooting scenarios,
for example when attempting to ensure that Nova has an existing and correctly
updated volume attachment recorded.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator or user I want to be able to confirm the id of the Cinder volume
attachment associated with a given block device mapping record within Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Introduce a new microversion that will display the volume attachment id of a
given block device mapping record in the response of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/servers/{server_id}/os-volume_attachments&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/servers/{server_id}/os-volume_attachments/{volume_id}&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could provide this information to operators via a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command
however that would require DB access and wouldn’t be available to users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attachment_id&lt;/span&gt;&lt;/code&gt; is already stored for each block device mapping record.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;In a new microversion, expose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attachmentId&lt;/span&gt;&lt;/code&gt; in the following responses:&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;While implementing this spec it was agreed that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt; field that
duplicates the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volumeId&lt;/span&gt;&lt;/code&gt; field would be removed under this microversion
with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt; of the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object also
added under a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bdm_uuid&lt;/span&gt;&lt;/code&gt; field.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/os-volume_attachments&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d5e4ae35-ac0e-4311-a8c5-0ee863e951d9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"227cc671-f30b-4488-96fd-7d0bf13648d8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1ce1a7ee-c88c-41ce-a4d3-ce78b1ab20bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bdm_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2420cbab-4aef-409f-97c0-b60c0e1d6902"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d5e4ae35-ac0e-4311-a8c5-0ee863e951d9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"810511b1-ab87-4f42-9033-199543376ddb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bdm_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e50caeba-b3f0-4a59-9973-7125d232d511"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/servers/{server_id}/os-volume_attachments/{volume_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2aad99d3-7aa4-41e9-b4e6-3f960b115d68"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"attachmentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1ce1a7ee-c88c-41ce-a4d3-ce78b1ab20bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"bdm_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2420cbab-4aef-409f-97c0-b60c0e1d6902"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None, operators and users have access to the underlying attachment details via
the Cinder attachments API, all we are exposing here is the mapping of the
volume attachment to the block device mapping record within Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;volume-attachments&lt;/span&gt; &lt;span class="pre"&gt;$SERVER&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;volume&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;
&lt;span class="pre"&gt;$SERVER&lt;/span&gt;&lt;/code&gt; commands will be extended to expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attachment_id&lt;/span&gt;&lt;/code&gt; when
provided with a high enough microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;API schema, functional and tempest integration tests will be written.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API reference, microversion history, openstackclient and novaclient docs
will be updated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Configurable Instance Hostnames</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/configurable-instance-hostnames.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/configurable-instance-hostnames"&gt;https://blueprints.launchpad.net/nova/+spec/configurable-instance-hostnames&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow users to specify an explicit hostname for their instance when creating
instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova publishes hostnames for instances via the metadata service and config
drives. This hostname is based on a sanitized version of the instance display
name combined with the domain value specified in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;dhcp_domain&lt;/span&gt;&lt;/code&gt;. As part
of the discussion around &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1581977"&gt;bug 1581977&lt;/a&gt;, it was noted that there is currently
no way to explicitly specify a hostname and decouple it from the display name.
We use the instance’s hostname when &lt;a class="reference external" href="https://docs.openstack.org/neutron/victoria/admin/config-dns-int.html"&gt;DNS integration is enabled in neutron&lt;/a&gt;,
and this can result in a lack of control over hostnames, preventing users doing
reasonable things like naming their instances based on the fully-qualified
domain name that the instance will eventually be available at.&lt;/p&gt;
&lt;p&gt;Correct this gap by allowing users to specify an explicit hostname when
creating instances.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I wish to specify an explicit hostname rather than relying on a
(poorly) sanitized version of the display name.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Allow users to pass an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; field when creating new
server(s) (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;) and when updating an existing server
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{id}&lt;/span&gt;&lt;/code&gt;). This &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute will have the following
constraints:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It must be 63 characters or less&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It must consist of alphanumeric characters and dashes (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-&lt;/span&gt;&lt;/code&gt;). Periods,
underscores, and other characters outside this set will be rejected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It cannot end in a dash&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where multiple instances are requested, hostnames will be suffixed with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-{idx}&lt;/span&gt;&lt;/code&gt;, where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{idx}&lt;/span&gt;&lt;/code&gt; is a 1-based index. If the combined name and suffix
would exceed the 63 character limit, the name will be rejected.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-EXT-SRV-ATTR:hostname&lt;/span&gt;&lt;/code&gt; instance attribute, which is currently
admin-only, will now be shown for non-admin users, since it doesn’t make sense
to allow users to configure the value but not see it.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove support for neutron’s DNS integration features and require users
explicitly create and configure ports with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; attribute before
creating the instance. This places extra work on nova and will result in a
worse user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbid creation of multiple instances when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute is
provided, similar to how we forbid this when a port is provided. This is
reasonable but will require a little more effort from users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start rejecting instance names that are not valid hostnames. This is a
significant breaking change that will impact many users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; object and corresponding database model and table
already have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; field/column.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new microversion will be introduced. When this microversion is used,
users will be able to pass an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; field when creating new
server(s) (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;) and when updating an existing server
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{id}&lt;/span&gt;&lt;/code&gt;). This &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute will have the following
constraints:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It must be 63 characters or less&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It must consist of alphanumeric characters and dashes (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-&lt;/span&gt;&lt;/code&gt;). Periods,
underscores, and other characters outside this set will be rejected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It cannot end in a dash&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where multiple instances are requested, hostnames will be suffixed with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-{idx}&lt;/span&gt;&lt;/code&gt;, where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{idx}&lt;/span&gt;&lt;/code&gt; is a 1-based index. If the combined name and suffix
would exceed the 63 character limit, the name will be rejected.&lt;/p&gt;
&lt;p&gt;When updating the hostname of an existing instance, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; attribute
of the port(s) in neutron will be updated, as will the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute
exposed via the metadata service.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-EXT-SRV-ATTR:hostname&lt;/span&gt;&lt;/code&gt; instance attribute, which is currently
admin-only, will now be accessible by non-admin users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None. Hostnames will be validated by both the nova API and neutron to prevent
invalid hostnames.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The neutron documentation will need to be updated to reflect the changes in
behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make necessary changes to nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update neutron documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested via Tempest tests, though this will likely require the
&lt;a class="reference external" href="https://github.com/openstack/designate-tempest-plugin"&gt;designate-tempest-plugin&lt;/a&gt; package. The bulk of the lifting will be done
with functional and unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Both nova and neutron’s documentation will need to be updated to reference this
functionality. The api-ref will be updated to document the new fields allowed
in the API requests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1581977"&gt;https://bugs.launchpad.net/nova/+bug/1581977&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/764482"&gt;https://review.opendev.org/c/openstack/nova/+/764482&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2020-November/019113.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2020-November/019113.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Support for generic mediated devices</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/generic-mdevs.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/generic-mdevs"&gt;https://blueprints.launchpad.net/nova/+spec/generic-mdevs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As Nova already supports to manage existing mediated devices via the libvirt
driver for virtual GPUs, we would want to help the operator to use this for
generic PCI devices that use the VFIO-mdev framework but aren’t GPUs.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As the Linux kernel supports a framework that’s called &lt;a class="reference external" href="https://www.kernel.org/doc/html/latest/driver-api/vfio-mediated-device.html"&gt;VFIO-mdev&lt;/a&gt; , hardware
vendors can use it for their devices, like &lt;a class="reference external" href="https://docs.nvidia.com/grid/latest/grid-vgpu-user-guide/index.html#creating-vgpu-device-red-hat-el-kvm"&gt;nVidia does for their GPUs&lt;/a&gt;. For
example, you can create virtual GPUs by asking the kernel to create a new
mediated device to the parent. As this API is abstract, any hardware could use
this framework for supporting the fact to create a virtual device off the
physical device.&lt;/p&gt;
&lt;p&gt;In the Queens release, the libvirt driver gains support for looking up
existing mediated devices for enable &lt;a class="reference external" href="https://github.com/openstack/nova/blob/771ea5bf1ea667d6ffe456ee6ef081b83a77f53c/nova/virt/libvirt/driver.py#L7463"&gt;managing virtual GPUs&lt;/a&gt; and can also
directly call the kernel API to &lt;a class="reference external" href="https://github.com/openstack/nova/blob/771ea5bf1ea667d6ffe456ee6ef081b83a77f53c/nova/virt/libvirt/driver.py#L7818"&gt;creating a new mediated device if needed&lt;/a&gt;.
Unfortunately, while this kernel API is abstract in terms of usability between
different physical devices supporting mediated devices, we created in Nova a
fake and unnecessary reciprocity between a virtual GPU and a mediated
device : a virtual GPU is indeed a mediated device, but a mediated device can
be something other than a virtual GPU.&lt;/p&gt;
&lt;p&gt;In this spec, we propose to remove this unrelated reciprocity by considering a
mediated device to be a distinct Placement resource class and not a virtual
GPU, if specified.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As currently, we only support stateless physical devices, as Nova
just reuses existing mediated devices between instances.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to provide new flavors for my customers that would
ask for generic mediated devices that aren’t virtual GPUs, as I already have
hardware that use VFIO-mdev fremework in the Linux kernel for abstracting
virtual resources.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We will minimize to the very least number of changes, that won’t be breaking
existing users of the virtual GPUs in Nova :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;we’ll just extend the configuration options for managing mediated devices in
Nova by proposing an extra option that will tell whether it’s for GPUs or
else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we’ll propose to use custom resource classes for scheduling decisions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing flavors won’t need to change.&lt;/p&gt;
&lt;section id="the-configuration-changes"&gt;
&lt;h3&gt;The configuration changes&lt;/h3&gt;
&lt;p&gt;Today, you can allow the Nova libvirt driver to use mediated devices for
virtual GPU management by defining in &lt;cite&gt;nova.conf&lt;/cite&gt; :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enabled_vgpu_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;type1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;type2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vgpu_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;type1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;device_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pci_address_1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pci_address_2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vgpu_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;type2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;device_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pci_address_3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We propose to rename the &lt;cite&gt;enabled_vgpu_types&lt;/cite&gt; option name with
&lt;cite&gt;enabled_mdev_types&lt;/cite&gt; and just use the old name as a legacy alias.
Accordingly, groups could be named &lt;cite&gt;mdev_&amp;lt;type&amp;gt;&lt;/cite&gt; or being kept as &lt;cite&gt;vgpu_&amp;lt;type&amp;gt;&lt;/cite&gt;
for a couple of releases.
An extra option could be specified under a &lt;cite&gt;mdev_&amp;lt;type&amp;gt;&lt;/cite&gt; group, named
&lt;cite&gt;mdev_class&lt;/cite&gt; and which could be defined as below :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mdev_class'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'vgpu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;regex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zA&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Z0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
           &lt;span class="n"&gt;max_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;248&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Class of mediated device to manage.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;An example would be as follows :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enabled_mdev_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nvidia&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mlx5_core&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mdev_nvidia&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;device_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mdev_mlx5_core&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;device_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;86&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.0&lt;/span&gt;
&lt;span class="n"&gt;mdev_class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mlx5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We already have &lt;a class="reference external" href="https://github.com/openstack/nova/blob/7953c0197d1a4466cb5b78070d47626c92f9db6e/nova/virt/libvirt/driver.py#L7357"&gt;configuration checks&lt;/a&gt; for this but we could try to
look at the inventories to detect unwanted changes if allocations
were create and prevent the compute service to start.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="the-custom-resource-classes"&gt;
&lt;h3&gt;The custom resource classes&lt;/h3&gt;
&lt;p&gt;Nothing really fancy here. The Nova libvirt driver will lookup at existing
PCI devices that support mediated devices and create inventories as of now.
The only difference is that if a PCI device is set as something other than the
default &lt;cite&gt;vgpu&lt;/cite&gt; class, then the inventory of the number of virtual devices it
can create for the specific type will use a custom resource class named
&lt;cite&gt;CUSTOM_&amp;lt;type&amp;gt;&lt;/cite&gt;.
For example, in the example above, inventories of physical devices using the
&lt;cite&gt;mlx5&lt;/cite&gt; mdev class will have resources of a class named &lt;cite&gt;CUSTOM_MLX5&lt;/cite&gt; (we
will convert the characters to uppercase in order to be accepted by the
Placement API).&lt;/p&gt;
&lt;p&gt;Accordingly, if a flavor specifies an extraspec with resource groups like
&lt;cite&gt;resources:CUSTOM_MLX5=1&lt;/cite&gt;, then Placement will create allocations on a Resource
Provider with this resource class. When, later in the boot sequence, the
libvirt driver will get allocations for the instance in the &lt;cite&gt;spawn()&lt;/cite&gt; method
(or for other move operations), it will not only lookup at the &lt;cite&gt;VGPU&lt;/cite&gt; related
allocations but also the &lt;cite&gt;CUSTOM_MLX5&lt;/cite&gt; ones and will consequently either bind
an existing mdev or ask sysfs to create a new one. In order to do it, the
driver will first look at all the custom resource classes that are accepted
by the configuration options above.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could describe the capacity with the new inventory YAML files but this would
disrupt a bit more existing users of the framework.
Another alternative could be to stop using the VGPU resource class and just
use the new MDEV resource class but this is a more breaking change for users
which would potentially require to modify existing allocations. Besides, other
virt drivers could continue to use the VGPU resource class, which would mean
a discrepancy between virt drivers.&lt;/p&gt;
&lt;p&gt;Cyborg can also be an obvious alternative as they start implementing virtual
GPUs too. There are no problems with having both projects supporting generic
devices as we let the operator choose what they prefer in terms of maintenance
and usage while the code itself is mostly shared (as eventually the mdev
allocation from Cyborg reuses the same methods).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.
Currently, all operations but live migration are supported and we don’t see the
need to propose a microversion for users opting into generic devices. As
flavors are managed by operators, there wouldn’t be visible changes for the
end users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;See the configuration options described above.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Potentially other virt drivers could use the opportunity to propose generic
devices too, mainly the Xen driver which already supports virtual gpus.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None as existing flavors and inventories won’t change. We will specify to only
use the new generic class for new hardware in order to prevent unneeded and
unnecessary Placement inventories modifications, but this isn’t really changing
the situation where some operator decides to reshuffle their GPUs with
different types.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sylvain-bauza&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Amend the libvirt driver to populate inventories of custom resource classes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amend the libvirt methods to look at allocations of known custom resource
classes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose the configuration changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Good news are, we could use the &lt;a class="reference external" href="https://www.kernel.org/doc/html/latest/driver-api/vfio-mediated-device.html#using-the-sample-code"&gt;mtty fake driver&lt;/a&gt; for testing generic mdevs
(and by extend virtual GPU management in Nova) with Tempest without relying on
some proprietary and expensive driver which is impossible with our upstream
gate jobs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Mostly &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/virtual-gpu.html"&gt;https://docs.openstack.org/nova/latest/admin/virtual-gpu.html&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Provide nova-manage commands to refresh block device mapping connection_info</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/nova-manage-refresh-connection-info.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-manage-refresh-connection-info"&gt;https://blueprints.launchpad.net/nova/+spec/nova-manage-refresh-connection-info&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The connection_info associated with a Cinder volume attachment stashed within
Nova’s block device mappings can often become stale. Previously operators have
had to query the database directly for an understanding of the current state of
the connection_info and could only migrate or shelve the instance to force a
refresh of this.&lt;/p&gt;
&lt;p&gt;This spec aims to outline some basic and potentially backportable
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; commands that will allow operators to both view and refresh the
connection_info of a specific block device mapping within Nova.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As suggested above the connection_info of a given volume attachment is stashed
within the block device mapping record associated with an attached volume
within Nova. Over time this connection_info can become stale if changes are
made in the environment, the most common example of which being the changing of
MON IP addresses when using Ceph as the backing store for the Cinder volume
service.&lt;/p&gt;
&lt;p&gt;There have also been various migration rollback issues over the years where the
connection_info associated with the block device mapping can actually refer to
that used by another compute host.&lt;/p&gt;
&lt;p&gt;In both cases until now the only way to force a refresh of the connection_info
was through another migration or shelve/unshelve that could also fail during
the initial disconnect of the volume.&lt;/p&gt;
&lt;p&gt;As such providing operators with a reliable means with which to refresh this
connection_info would be extremely useful.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to view the current connection_info associated with a
block device mapping.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to refresh the connection_info of block device mappings
attached to a user’s STOPPED instance without shelving and unshelving.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Introduce a set of backportable &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; commands to manage the
connection_info associated with a given volume attachment.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$bdm_uuid&lt;/span&gt;&lt;/code&gt; below refers to the UUID of the block device mapping record&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;within Nova and not the volume attachment UUID within Cinder. Block device
mapping UUIDs for attached volumes can be obtained using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt;
&lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;volume&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt; &lt;span class="pre"&gt;$instance_uuid&lt;/span&gt;&lt;/code&gt; command with openstackclient &amp;gt;= 5.5.0
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;volume-attachments&lt;/span&gt; &lt;span class="pre"&gt;$instance_uuid&lt;/span&gt;&lt;/code&gt; novaclient command.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;section id="add-a-command-to-show-the-connection-info-of-a-given-block-device-mapping"&gt;
&lt;h3&gt;Add a command to show the connection_info of a given block device mapping&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;bdm&lt;/span&gt; &lt;span class="pre"&gt;show&lt;/span&gt; &lt;span class="pre"&gt;$bdm_uuid&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This command will simply show &lt;em&gt;all&lt;/em&gt; attributes of the volume attachment as
currently stored within the Nova database.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This should also be accomplished within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-volume_attachments&lt;/span&gt;&lt;/code&gt;
API under a microversion but for the sake of this spec we will only focus on
the above backportable &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="add-a-command-to-refresh-the-connection-info-of-a-given-block-device-mapping"&gt;
&lt;h3&gt;Add a command to refresh the connection_info of a given block device mapping&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$&lt;/span&gt; &lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;bdm&lt;/span&gt; &lt;span class="pre"&gt;refresh&lt;/span&gt; &lt;span class="pre"&gt;$bdm_uuid&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This command will refresh the connection_info of a given volume based
block device mapping record within Nova.&lt;/p&gt;
&lt;section id="prerequisites"&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The block device mapping refers to an attached volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The instance the block device mapping is attached to must be in a STOPPED
vm_state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The libvirt virt driver is used by the compute hosting the instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When these prerequisites are met the command will start by locking the instance
to ensure no user requests will be accepted and potentially race the refresh
of the connection_info.&lt;/p&gt;
&lt;p&gt;Then the command will make an RPC call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remove_volume_connection&lt;/span&gt;&lt;/code&gt; on the
compute hosting the instance disconnecting the original volume connection from
the compute host using the existing logic within the libvirt virt driver volume
drivers.&lt;/p&gt;
&lt;p&gt;The call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;remove_volume_connection&lt;/span&gt;&lt;/code&gt; will also unmap the volume from the
compute host via Cinder by either calling the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;terminate_connection&lt;/span&gt;&lt;/code&gt; API for
volumes attached using the cinderv2 attachment flow or by deleting the volume
attachment for volumes using the cinderv3 attachment flow.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We cannot precreate a fresh volume attachment for the cinderv3
attachment flow as the provided connector would conflict with the existing
attachment and thus result in a failure. This differs to the live migration
case where the source and destination connectors differ allowing us to have
two active volume attachments at once within Cinder.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Once the RPC call returns the command we create a fresh cinderv3 volume
attachment using the compute connector with the resulting attachment_id and
connection_info being stashed in the block device mapping record within Nova.&lt;/p&gt;
&lt;p&gt;This has the added benefit of migrating some volume attachments from the
cinderv2 to cinderv3 flow. While much more work is required outside of this
spec for Nova to migrate every volume attachment to the newer flow this is at
least a start on that journey.&lt;/p&gt;
&lt;p&gt;Finally, the instance will be unlocked allowing the user to now power on the
instance that will in turn connect the volume to the compute host using the
newly updated connection_info.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As with the earlier command this should also be accomplished within the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-volume_attachments&lt;/span&gt;&lt;/code&gt; API under a new microversion but again for the
sake of the spec we will only focus on the above backportable command.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to only allow connection_info to be updated by migrating or shelving
an instance. This doesn’t scale well and can often lead to more issues when
connection_info has become stale and out dated within an environment.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None, the connection_info for a given attachment is already available to the
owner of said attachment via Cinder. There is a case to make this an admin only
API under a microversion within Cinder in the future, using service credentials
within Nova to facilitate the passing of sensitive attributes like passwords,
tokens and keyrings but for now having a nova-manage command expose what is
stored in our database shouldn’t have an impact on our security model.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce a command to show the attributes of a block device mapping,
including the volume attachment id and connection_info.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a command to refresh the connection_info of a block device mapping.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional and unit tests will be written to validate these commands. We could
also include integration tests in the form of some post-run playbooks and runs
but this isn’t required for these commands to land.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;As with all nova-manage commands extensive operator facing documentation will
be written detailing commands.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Smartnic Management Overall Design</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/implemented/sriov-smartnic-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/sriov-smartnic-support"&gt;https://blueprints.launchpad.net/nova/+spec/sriov-smartnic-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes an overall design for smartnic management which will involve
Nova, Neutron and Cyborg changes. In this spec, we will introduce how to manage
the smartnic’s lifecycle, and how to attach a smartnic to the VM.
This spec aims at supporting VF management, the PF management is out-of-scope.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nowadays, various devices are made to run specific workloads which will free up
CPU resources. Smart-nic is a network device that can be used to offload the
network-related workload. It goes beyond simple connectivity and implements
network traffic processing on the NIC that would necessarily be performed by
the CPU in the case of a conventional NIC.&lt;/p&gt;
&lt;p&gt;In the current design, OpenStack can not manage and schedule a smart-nic in
terms of supported features and readable traits automatically.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Users want to boot up a VM with a specific port which is associated with a
smartnic resource managed by Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users want to boot vms that leverage pre-programmed functionality to offload
their workload to a smart-nic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are multiple projects(Nova, Neutron, Cyborg, and Placement) involved in
this feature.&lt;/p&gt;
&lt;section id="workflow"&gt;
&lt;h3&gt;Workflow&lt;/h3&gt;
&lt;p&gt;This workflow describes the basic operation to boot a VM with pre-programmed
nic.
The workflow can be divided into two parts:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Device discovery and report.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interaction when booting a VM.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="device-discovery"&gt;
&lt;h4&gt;Device discovery&lt;/h4&gt;
&lt;p&gt;Cyborg should implement a driver that the cyborg-agent can invoke periodically
to discover the smartnic resources. We will explain this part in detail in
Cyborg spec, please refer to &lt;a class="reference external" href="https://review.opendev.org/#/c/759545/"&gt;https://review.opendev.org/#/c/759545/&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="device-information-report"&gt;
&lt;h4&gt;Device information report&lt;/h4&gt;
&lt;section id="how-to-report-physnet-trait"&gt;
&lt;h5&gt;How to report physnet trait&lt;/h5&gt;
&lt;p&gt;As we know, Neutron has a config option physical_device_mappings indicating the
mapping relation between physical_network and network_device. Admin need to
maintain another configuration file (Please refer to 1 in the flowchart) that
contains the device’s name and the physical network name this device associate
to.
In this way, the Cyborg driver can directly read from this file and add a
physical network as a trait when reporting to Placement. The admin is
responsible to keep Cyborg’s and Neutron’s config file consistent, otherwise,
there will be a configuration conflict.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="co-existence-with-neutron-s-guaranteed-minimum-bandwidth-1-feature"&gt;
&lt;h5&gt;Co-existence with Neutron’s Guaranteed Minimum Bandwidth &lt;a class="footnote-reference brackets" href="#id14" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; Feature&lt;/h5&gt;
&lt;p&gt;According to Wallaby PTG discussion &lt;a class="footnote-reference brackets" href="#id15" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and the following discussions &lt;a class="footnote-reference brackets" href="#id16" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
in the community, we propose to not support co-existence with Neutron’s
Guaranteed Minimum Bandwidth Feature for the same physical device at the
first step, which means that one physical device can only be configured by
Cyborg or by Neutron’s QoS feature if it is enabled.&lt;/p&gt;
&lt;p&gt;The following flowchart illustrates the workflow during device discovery and
report:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;  &lt;span class="o"&gt;+----------------+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;cyborg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--------+-------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;+-------------+&lt;/span&gt;        &lt;span class="o"&gt;+-------------+&lt;/span&gt;
&lt;span class="o"&gt;+----------|---------+&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;cyborg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;conductor&lt;/span&gt;  &lt;span class="o"&gt;|-----------&amp;gt;|&lt;/span&gt;  &lt;span class="n"&gt;Placement&lt;/span&gt;  &lt;span class="o"&gt;|&amp;lt;-------|&lt;/span&gt;   &lt;span class="n"&gt;Neutron&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------|---------+&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;+-------------+&lt;/span&gt;        &lt;span class="o"&gt;+-------------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;+------------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------&amp;gt;|&lt;/span&gt;  &lt;span class="n"&gt;Cyborg&lt;/span&gt; &lt;span class="n"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--------|-------+&lt;/span&gt;               &lt;span class="o"&gt;+------------+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;cyborg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--------|-------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;+----------------+&lt;/span&gt;
  &lt;span class="o"&gt;+--------|-------+&lt;/span&gt;     &lt;span class="mi"&gt;1&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;  &lt;span class="o"&gt;|&amp;lt;----------|&lt;/span&gt;  &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+----------------+&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
                               &lt;span class="o"&gt;+----------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="interaction-when-booting-the-vm"&gt;
&lt;h4&gt;Interaction when booting the VM&lt;/h4&gt;
&lt;p&gt;Currently, Nova can interact with Cyborg to boot up a VM with an accelerator
like FPGA, GPU. And other operations such as hard/soft reboot, pause/unpause
are also supported. But there is no mechanism to let Nova boot up a VM with a
nic associated with a specific network. To implement this, it requires
Nova, Cyborg, and Neutron change. And this spec also covers the scenario about
reboot/pause/stop/start and other operations.&lt;/p&gt;
&lt;p&gt;Here we take the “boot a VM” scenario as an example. Assuming that Cyborg has
reported the nic resources and related traits correctly.
The workflow is proposed as the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt; &lt;span class="o"&gt;+-----------+&lt;/span&gt;      &lt;span class="o"&gt;+-----------+&lt;/span&gt; &lt;span class="o"&gt;+-----------+&lt;/span&gt;   &lt;span class="o"&gt;+-----------+&lt;/span&gt;   &lt;span class="o"&gt;+---------+&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;admin&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Neutron&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;Nova&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Placement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Cyborg&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="o"&gt;+-----|-----+&lt;/span&gt;      &lt;span class="o"&gt;+-----|-----+&lt;/span&gt; &lt;span class="o"&gt;+-----|-----+&lt;/span&gt;   &lt;span class="o"&gt;+-----|-----+&lt;/span&gt;   &lt;span class="o"&gt;+-------+-+&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;|-----------------------------------------------------------------&amp;gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----|-----+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|------------------&amp;gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|--------------------------------&amp;gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                       &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;physnet&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;

                          &lt;span class="o"&gt;|&amp;lt;------------|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                                                 &lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;-------------------------------&amp;gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="n"&gt;sheduling&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;-------------&amp;gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mf"&gt;7.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PCI&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;-------------------------------&amp;gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mf"&gt;8.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&amp;lt;------------|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|-----+&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;9.&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;SRIOV&lt;/span&gt; &lt;span class="n"&gt;VIF&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;libvirt&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt; &lt;span class="n"&gt;section&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;----+&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;1. Firstly, admin needs to create a device profile that contains the smartnic’s
description such as resource class, and traits. The CLI are already supported
as the following:&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;GRP=”[{“resources:CUSTOM_NIC”: “1”,”trait:CUSTOM_GTV1”:”required”}]”
openstack accelerator device profile create sriov_dp1 $GRP&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;2. Secondly, user needs to create a port by passing device profile as a
parameter. Related API needs to be added to operate this. And also,
Neutron need to add a new vnic-type for the nic managed by Cyborg, we can name
it “accelerator-direct” here. For example, we can create a port by: &lt;cite&gt;openstack
port create –network providernet –vnic-type accelerator-direct
–device-profile sriov-dp1 sriov_port1&lt;/cite&gt; in which &lt;cite&gt;sriov-dp1&lt;/cite&gt; is the device
profile created at the first step. Please notice that the device profile used
by a port should only have one device resource required, otherwise an exception
will be thrown out during the VM boot up process.&lt;/p&gt;
&lt;p&gt;The request body is the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"sriov-port1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"network_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a87cc70a-3e15-4acf-8205-9b711a3531b7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"vnic_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"accelerator-direct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"device_profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"sriov_dp1"&lt;/span&gt; &lt;span class="c1"&gt;# new extension contains device profile&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;3. Thirdly, user can boot up a VM by:
&lt;cite&gt;openstack server create –image image-uuid -flavor flavor-name  –nic
port-id=sriov_port1 test_vm1&lt;/cite&gt;.
(If the device profile used in the port contains multiple devices, this
API requests will fail with a 400 Error code.)&lt;/p&gt;
&lt;p&gt;4. Nova interacts with Neutron to get port’s details, including vnic type,
neutwork_id, physical network, etc.&lt;/p&gt;
&lt;p&gt;5. If the vnic type is “accelerator-direct”, then Nova need to extract the
“device_profile” extension of sriov_port1, and call Cyborg API to get details
of this device_profile &lt;a class="footnote-reference brackets" href="#id17" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, the ARQ creation is also in this step.&lt;/p&gt;
&lt;p&gt;6. In step 4, Nova has fetched the physical network from Neutron, now Nova need
to convert it into Placement’s trait format and save it in port’s resource
request field if vnic type is “accelerator-direct”. Then Nova need to merge the
resource class/trait obtained from Cyborg’s device profile and the port
resource request into a one single request group. And this request group will
be merged into request_spec which will be used in reboot/pause/start/stop and
other supported operations. After that, Nova schedules the VM to an available
compute node who matches all requested resources.&lt;/p&gt;
&lt;p&gt;7. After scheduling, Nova needs to call Cyborg to bind the ARQ with instance
uuid and return attach_handle which contains the device’s info such as PCI
address. An async binding job starts in Cyborg and Cyborg will send back a
notification once the binding operation finished.&lt;/p&gt;
&lt;ol class="arabic simple" start="8"&gt;
&lt;li&gt;&lt;p&gt;Nova waits for the notification from Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once Nova got the notification from Cyborg which indicates the binding
operation succeed, Nova needs to tell Neutron to update the port binding’s
info.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt driver need to insert SRIOV nic info to the XML section.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="api-calls"&gt;
&lt;h4&gt;API calls&lt;/h4&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Nova calls Neutron to get port details.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;request URL: /v2.0/ports/{port_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;response example(the new extension &lt;cite&gt;device_profile&lt;/cite&gt; should be returned):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
      &lt;span class="s2"&gt;"binding_profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"sriov-port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"network_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a87cc70a-3e15-4acf-8205-9b711a3531b7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"qos_network_policy_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"174dd0c1-a4eb-49d4-a807-ae80246d82f4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"qos_policy_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"29d5e02e-d5ab-4929-bee4-4a9fc12e22ae"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"device_profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"sriov-dp1"&lt;/span&gt; &lt;span class="c1"&gt;# new extension&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Nova calls Cyborg to get device profile’s details. &lt;a class="footnote-reference brackets" href="#id18" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova calls Cyborg to create and bind ARQs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create ARQ &lt;a class="footnote-reference brackets" href="#id19" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind ARQ &lt;a class="footnote-reference brackets" href="#id20" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait for “binding success” notification from Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;Nova call Neutron to update port binding profile with interface info. &lt;a class="footnote-reference brackets" href="#id21" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="neutron"&gt;
&lt;h3&gt;Neutron&lt;/h3&gt;
&lt;p&gt;In Neutron side, a new vnic type “accelerator-direct” need to be added, as well
as a new port extension “device_profile”. Please refer to Neutron’s RFE &lt;a class="footnote-reference brackets" href="#id22" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
for details.&lt;/p&gt;
&lt;p&gt;The proposed change includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new vnic type “accelerator-direct” indicating the port associated with
device managed by Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define device profile extension for port in neutorn lib.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement device profile extension for port in Neutron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From DB side, we need to add a new table to store the mapping relation
between port and device_profile:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+---------------------------------------+------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;port_uuid&lt;/span&gt;                             &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;device_profile&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+=======================================+========================+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="n"&gt;f78856&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f73&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;cf4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bcd0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1389086&lt;/span&gt;&lt;span class="n"&gt;eb038&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sriov_dev_profile&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+---------------------------------------+------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please refer to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Port resource request definition &lt;a class="footnote-reference brackets" href="#id23" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;10&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;neutron-lib port-resource-request Commits &lt;a class="footnote-reference brackets" href="#id24" id="id11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;11&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;neutron plugin port-resource-request Commits &lt;a class="footnote-reference brackets" href="#id25" id="id12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;12&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="nova"&gt;
&lt;h3&gt;Nova&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova API: Nova calls Neutron API to get port details, including vnic type,
physical network etc.
“device_profile” should be returned as the return value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API: Nova need to check if vnic type is “accelerator-direct”. If so,
Nova will get the device profile’s name from neutron port and call Cyborg
API to get the details of this device profile. Meanwhile, Nova need to
generate a trait for physical network, for example, Nova get “physnet1” as
the physical network from Neutorn, the trait should looks like
“CUSTOM_PHYSNET_PHYSNET1”, which is consistent with what Cyborg reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API: Once Nova gets all resource classes and traits, Nova should check
if a RequestGroup is created with port_resource_request, if so, we should add
resource and traits to this request group, if not, we should generate a new
resource group. Nova should have one single request_group to schedule to a
single nic resource provider &lt;a class="footnote-reference brackets" href="#id26" id="id13" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;13&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This request_group store the requested
resource information used by the scheduler, and other operations, such as
reboot/pause/unpause/start/stop, will use this request_group to do the
scheduling as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova Compute: Nova should update port binding profile with sriov nic’s info
(such as pci adderess etc), so that libvirt driver can generete related xml
section.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="cyborg"&gt;
&lt;h3&gt;Cyborg&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A new driver needs to be added in Cyborg in order to discover, program and
bind the device. More details is in the Cyborg spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cyborg needs to implement a device config file to configure the nic’s
name, pci address, physnet name, etc, which are used for Cyborg driver to
generate resource provider, trait, etc.&lt;/p&gt;
&lt;div class="highlight-RST notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;[dev-type]
physical_device_mappings = physnet1:eth2|eth3
function_device_mappings = GTPv1:eth3|eth2
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="who-reports-physnet-trait"&gt;
&lt;h4&gt;Who reports physnet trait&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Placement CLI to add trait.&lt;/p&gt;
&lt;p&gt;Admin need to add physnet trait to resource provider manually, this will be
done after Cyborg reports resource to Placement. It will cause redundant
Placement API call as well.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron report trait for the resource provider created by Cyborg.&lt;/p&gt;
&lt;p&gt;In this way, Neutron should firstly get a resource provider created by Cyborg
by Placement API, and Neutron also need to find the right physnet tratis
according to nic’s resource, which requires more changes in Neutron.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let Neutron create RP and physnet trait.&lt;/p&gt;
&lt;p&gt;As we know, Neutron will create RP and related traits when minimum bandwidth
QoS is configured. We propose that Neutron could always report RP and physnet
traits all the time, no matter the bandwidth qos configured or not. In this
way, Cyborg will just find the RP created by Neutron by using some name
convention, and add accelerator-related traits to this RP.&lt;/p&gt;
&lt;p&gt;But we should consider how the RP tree structure look like when Neutron
report it, should it be directly under compute node RP, or still under Agent
RP like bandwidth qos feature does.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="how-nova-generate-request-spec-with-request-device"&gt;
&lt;h4&gt;How Nova generate request_spec with request device&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Neutron calls Cyborg API to get device profile details and merge all RC and
trait into port_resource_request, then return to Nova.
By retriving the device profile in neutron from Cyborg, this allows Neutron
to validate the device profile contains only 1 device request. This check
will instead be enforced by Nova.&lt;/p&gt;
&lt;p&gt;It requires Neutron changes to interact with Cyborg, which seems that Cyborg
is a sub-component for Neutron. It’s better to let Nova interact with Cyborg
and Neutron equally.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a new DeviceProfileRequest to store the device profile’s request
group, and pass it as a new parameter when Nova generates request_spec.&lt;/p&gt;
&lt;p&gt;It seems to be redundant to have a new request object.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="others"&gt;
&lt;h4&gt;Others&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cyborg provides its own SRIOV ML2 driver for the NICs it supports.&lt;/p&gt;
&lt;p&gt;Cyborg maintains a Neutron plugin driver that exceeds Cyborg project’s scope.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ARQ’s consumer could be a port instead of instance uuid.&lt;/p&gt;
&lt;p&gt;During ARQ binding, Nova wait for an external event from Cyborg which is
queried by instance uuid. We need keep it same as the workflow for the
request from flavor.extra_specs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;New table &lt;cite&gt;device_profile&lt;/cite&gt; needs to be added in Neutron DB.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new extension ‘device_profile’ will be added in Neutron port, Neutron API
need changes. Neutron API should also forbid user to modify ‘device_profile’
field once the port is bound with one instance(Neutorn API need to check the
binding:host-id before updating the ‘device profile’ field.). This
modification is only allowed when the port is unbound.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change Nova APIs for more operation supports. We plan to support
create/delete, start/stop, pause/unpause, rebuild, reboot, lock/unlock,
rescue/unrescue for a VM having an “accelerator-direct” vnic type port,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since neutron port can not be associated to multiple NICs, only the device
profile with one device group is accepted to a port. Otherwise an exception
will be raised with HTTP 400 Error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the operation is not supported, it will be rejected with an HTTP 400
Error.
Case 1: If there are compute nodes with old service versions not support this
feature, the lifecycle operations of server with ports with device_profile
need to be rejected with HTTP 400 Error.
Case 2: For the operation we don’t support, such as evacuate, resize,
migration, shelve/unshelve operations for a VM having an “accelerator-direct”
vnic type port, and attac/detach an “accelerator-direct” vnic type port
to/from a VM, an HTTP 400 Error will be returned as well.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova needs to adapt to the new Neutron API extension introducing the
device_profile in the port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova compute service version needs to be bumped and server lifecycle
operations on server with ports with device_profile needs to be rejected if
the minimun version of all compute services not satisfy the lowest
requirement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Yongli He(&lt;a class="reference external" href="mailto:yongli.he%40intel.com"&gt;yongli&lt;span&gt;.&lt;/span&gt;he&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Xinran Wang(&lt;a class="reference external" href="mailto:xin-ran.wang%40intel.com"&gt;xin-ran&lt;span&gt;.&lt;/span&gt;wang&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new port extension in Neutron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a new driver for specific nic in Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a configuration file in Cyborg to handle physnet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parse and merge request into request spec in Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind ARQ to instance uuid and update port binding profile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-use the current sriov nic xml generation code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Need to add UT in the involved project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional test in Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest test in Nova if necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest test in cyborg-tempest-plugin.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Need to add documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id14" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html"&gt;https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-wallaby-ptg"&gt;https://etherpad.opendev.org/p/nova-wallaby-ptg&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2020-11-09.log.html#t2020-11-09T05:48:48"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2020-11-09.log.html#t2020-11-09T05:48:48&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id17" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html?expanded=#list-device-profiles"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html?expanded=#list-device-profiles&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id18" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html#list-device-profiles"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html#list-device-profiles&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id19" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html#create-accelerator-requests"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html#create-accelerator-requests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id20" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html#update-accelerator-requests"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html#update-accelerator-requests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id21" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/network/v2/#update-port"&gt;https://docs.openstack.org/api-ref/network/v2/#update-port&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id22" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1906603"&gt;https://bugs.launchpad.net/neutron/+bug/1906603&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id23" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;10&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/508149/14/specs/rocky/minimum-bandwidth-allocation-placement-api.rst"&gt;https://review.opendev.org/#/c/508149/14/specs/rocky/minimum-bandwidth-allocation-placement-api.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id24" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id11"&gt;11&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron-lib/search?q=port-resource-request&amp;amp;type=Commits"&gt;https://github.com/openstack/neutron-lib/search?q=port-resource-request&amp;amp;type=Commits&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id25" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id12"&gt;12&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/search?q=port-resource-request&amp;amp;type=Commits"&gt;https://github.com/openstack/neutron/search?q=port-resource-request&amp;amp;type=Commits&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id26" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id13"&gt;13&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/placement/latest/user/provider-tree.html#granular-resource-requests"&gt;https://docs.openstack.org/placement/latest/user/provider-tree.html#granular-resource-requests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id27"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 Oct 2021 00:00:00 </pubDate></item><item><title>Remove tenant_id</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/remove-tenant-id.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-tenant-id"&gt;https://blueprints.launchpad.net/nova/+spec/remove-tenant-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The blueprint proposes to remove the API interface that uses
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and replace it with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Nova API supports both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;,
which is unfriendly to users.&lt;/p&gt;
&lt;p&gt;The following is a confusing question.
By default, we support filtering instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt; &lt;span class="pre"&gt;(Optional)&lt;/span&gt;&lt;/code&gt;,
but through this parameter, we get a list of all instances that they
cannot get instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can see from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1185290"&gt;bug 1185290&lt;/a&gt; that when using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt; command,
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; is required, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; must appear, as description
in &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, which is somewhat unintuitive.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;a class="footnote-reference brackets" href="#id3" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; mainly said: “As explained in lp:#1185290, if &lt;cite&gt;all_tenants&lt;/cite&gt;
is not passed we must ignore the &lt;cite&gt;tenant_id&lt;/cite&gt; search option.”.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can know from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1468992"&gt;bug 1468992&lt;/a&gt; that many users want to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;
filtering instances, and using the concept of tenants in many of our
large-scale customer scenarios, they hope we can filter the expected
instances through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an (admin) user, I would like to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; uniformly in nova api,
instead of supporting both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;, this will imporve
uniformity within nova and between nova and other service which have already
made this change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to the request or response parameter changes API.&lt;/p&gt;
&lt;p&gt;Remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; field, using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt;
parameter, and then remove``all_tenants`` parameter in the following APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The keyword &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; in the path will be replaced with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; as below
APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage/{tenant_id}&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage/{project_id}&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We should block change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; below the deprecated APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups (List Security Groups)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups/{security_group_id} (Show Security Group Details)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-security-groups/{security_group_id} (Update Security Group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /os-security-group-rules (Create Security Group Rule)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-fping?all_tenants=1 (Ping Instances)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, tenant* reference will be replaced with project* in all policies,
code and docs too.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a new microversion.&lt;/p&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; parameter, and remove
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Update openstacksdk, python-novaclient and python-openstackclient
for the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the python-novaclient , python-openstackclient and openstacksdk,
just support requesting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in related APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test for negative scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test (API samples).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary for this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the API reference for the new microversion, and update all uses of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; in all docs and code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Mainly info: &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295"&gt;https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sun, 19 Sep 2021 00:00:00 </pubDate></item><item><title>volume-backed server rebuild</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/volume-backed-server-rebuild.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/volume-backed-server-rebuild"&gt;https://blueprints.launchpad.net/nova/+spec/volume-backed-server-rebuild&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, the compute API will &lt;a class="reference external" href="https://github.com/openstack/nova/blob/62245235b/nova/compute/api.py#L3318"&gt;fail&lt;/a&gt; if a user tries to rebuild
a volume-backed server with a new image. This spec proposes to add
support for rebuilding a volume-backed server with a new image.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Nova rebuild (with a new image) only supports instances which are
booted from images. The volume-backed instance cannot be rebuilt when a new
image is supplied. Trying to rebuild a volume-backed instance will raise a
HTTPBadRequest exception.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user, I would like to rebuild my volume-backed server with a new image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a nova developer, I would like to have feature parity in the compute API
for volume-backed and image-backed servers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;First, change the existing API for rebuilding a volume-backed server.
Then the API flow would be:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A new request parameter, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reimage_boot_volume&lt;/span&gt;&lt;/code&gt; (boolean), will be added
to the existing reimage API call which, if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, will indicate if the
user wants to reimage a volume backed instance. By default, it will be
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reject the request if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reimage_boot_volume&lt;/span&gt;&lt;/code&gt; is passed as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; and the
instance isn’t booting from a volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Has the new API microversion been requested. If it is old API microversion
request, then it should be 400 returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a COMPUTE_REBUILD_BFV trait for knowing if the compute node can
support volume-backed server rebuild.
if not, will raise RebuildVolumeBackedServerNotSupport exception.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the cinder microversion is new enough to support reimage
the boot volume. If not, will raise CinderAPIVersionNotAvailable
exception.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In case of multiattach volumes, n-api will reject the request since
rebuilding multiattach volumes require complex attachment handling and
the effort would outweigh the benefit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then the nova-compute manager will perform the following steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create an empty (no connector) volume attachment for the volume and
server. This ensures the volume remains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt;&lt;/code&gt; through the next
step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the existing volume attachment (the old one).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the new attachment UUID to the BDM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The above two steps are needed to keep the volume in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt;&lt;/code&gt; state
as a management state which is required by cinder to perform re-image
operation on it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-reimage&lt;/span&gt;&lt;/code&gt; cinder API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new ‘volume-reimaged’ external event to wait for cinder to
complete the reimage. Like we use for volume-extend.
See &lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/454322"&gt;perform_resize_volume_online&lt;/a&gt; for details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After successful completion of the re-image operation, cinder will notify
Nova via external events API that the reimage operation is completed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call cinder to Update the empty volume attachment by passing the connector
info and cinder will return connection info to Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After Nova completes the connection with brick, complete the attachment
marking the volume &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in-use&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this process, there are some conditions that we could hit:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If we failed to re-image the volume and the volume is in ‘error’ status
then we should set the instance status as “error”. Since users can rebuild
instances in error status, the user has a way to retry the rebuild once
the cause of the cinder side failure is resolved. Note that nova-compute
will &lt;em&gt;not&lt;/em&gt; attempt to update the volume attachment records with the host
connector again on the volume in error status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the cinder API itself returns a &amp;gt;=400 error, nothing changed about the
root volume and in that case the instance action should be ‘failed’ and the
instance status should go back to what it was (we can see how
_error_out_instance_on_exception is used).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The main alternative is that nova would perform the rebuild like an initial
boot from volume where nova-compute would create a new volume from the new
image and then replace the root volume on the instance during rebuild.&lt;/p&gt;
&lt;p&gt;There are issues with this, however, like what to do about the old volume:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Regarding ‘delete_on_termination’ flag in the BDM,
delete_on_termination=True means: delete the volume when we kill
the instance. Rebuild means: re-initialize this instance in place. The
rebuild flow would have to determine what to do if the old root volume
BDM was marked with delete_on_termination=True. If delete_on_termination
is True, delete the old root volume, otherwise, preserve it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could pass a new flag to the rebuild API telling nova what to do about the
old volume (delete it or not).
If the flag is true to delete the old volume but the old volume has
snapshots, Nova won’t be deleting the volume snapshots just to delete
the volume during a rebuild.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are several issues with that as mentioned above like quota and
the questions about what nova should do about the old volume, you can
see more detailed information in &lt;a class="reference internal" href="#references"&gt;References&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a new parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reimage_boot_volume&lt;/span&gt;&lt;/code&gt; (boolean) to the existing rebuild
API.&lt;/p&gt;
&lt;div class="highlight-console notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="go"&gt;POST /servers/{server_id}/action&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"rebuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"reimage_boot_volume"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Change the rebuild request response code from 400 to 202 if the conditions
described in the &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt; section are met.
The API microversion and compute RPC version will also be incremented to
indicate the new support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The python-novaclient, python-openstackclient and SDK will be updated
to support the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The operation will take longer because of the external dependency
involved and the work that needs to happen in Cinder.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If the cinder volume &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reimage&lt;/span&gt;&lt;/code&gt; API operation fails and the volume goes to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; status, an admin will likely need to investigate and resolve the
issue in cinder and then reset the volume status to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The API microversion and compute service version will also be incremented
to indicate the new support, therefore users will not be able to leverage
the feature until the nova-compute service hosting a volume-backed instance
is upgraded.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Rajat Dhasmana &amp;lt;&lt;a class="reference external" href="mailto:rajatdhasmana%40gmail.com"&gt;rajatdhasmana&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt; (whoami-rajat)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new request parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reimage_boot_volume&lt;/span&gt;&lt;/code&gt; to the rebuild API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the existing rebuild API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an empty attachment for the root volume so the volume
remains in-use during rebuild (we do this today already).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the old volume attachment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call the cinder API to re-image the volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update and complete the volume attachment once re-imaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adopt the new compute version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adopt the new microversion in python-novaclient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adopt the new microversion in python-openstackclient.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Depends on the cinder blueprint for re-imaging a volume, see
more detail information in References.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The following tests are added.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova unit tests for negative scenarios&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova functional tests for “happy path” testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest integration tests to make sure the nova/cinder integration
works properly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We will replace the &lt;a class="reference external" href="https://developer.openstack.org/api-ref/compute/?expanded=#rebuild-server-rebuild-action"&gt;note in the API reference&lt;/a&gt; with
a note about the required minimum microversion for rebuilding a
volume-backed server with a new image.&lt;/p&gt;
&lt;p&gt;The following document will be updated:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API Reference&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We also need to mention in the documentation that when the volume
is re-imaged, all current content on the volume will be &lt;em&gt;destroyed&lt;/em&gt;.
This is important as cinder volumes are considered to be persistent,
which is not the case with this operation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stein PTG etherpad: &lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-ptg-stein"&gt;https://etherpad.openstack.org/p/nova-ptg-stein&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is the discussion about rebuild the volume-backed server:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2017-October/123255.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2017-October/123255.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is the discussion about what we should do about the root volume
during a rebuild:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-operators/2018-March/014952.html"&gt;http://lists.openstack.org/pipermail/openstack-operators/2018-March/014952.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The cinder blueprint for re-imaging a volume:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/cinder/+spec/add-volume-re-image-api"&gt;https://blueprints.launchpad.net/cinder/+spec/add-volume-re-image-api&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions
   :header-rows: 1&lt;/span&gt;&lt;/caption&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 17 Sep 2021 00:00:00 </pubDate></item><item><title>Add a nova-audit service for periodic maintenance</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/nova-audit.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-audit"&gt;https://blueprints.launchpad.net/nova/+spec/nova-audit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova is a distributed system, which means that things fail in strange
ways and data stored across multiple systems gets out of sync with the
actual state of reality. Hosts and instances come and go, along with
network connectivity, the message bus and database. Recently we have
gained a number of “heal $thing” routines that operators can run
either periodically or on demand to synchronize the states of various
services and data stores to resolve or prevent problems. The number of
these tasks is already overwhelming for the average operator, and
tracking new tasks each cycle is not realistic &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As described above, we have an increasing number of maintenance tasks
that need to be run in various scenarios. In most cases, these tasks
are idempotent and safe to run even when nothing is wrong. Operators
need a single mechanism for performing these maintenance tasks and
healing activities that can be run periodically in the background with
minimal impact to runtime performance, other than to hopefully fix
problems related to inconsistencies before they become acute enough to
get an human involved.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I would like Nova to heal itself whenever possible to
minimize the number of support incidents requiring human intervention.&lt;/p&gt;
&lt;p&gt;As a user, I would like Nova to heal itself whenever possible to avoid
having to involve support for transient issues, which may be
impossible or expensive, especially during off-hour periods.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We already have a number of these maintenance activities codified in
one-shot commands &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; that can be run on-demand once a problem has been
identified. Since most of them are not harmful or overly expensive, we
should be able to run those things periodically to attempt to fix
problems automatically before the operator gets involved.&lt;/p&gt;
&lt;p&gt;This spec proposes a new binary called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt; to encapsulate
these tasks. Ideally it should be usable in multiple ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a singleton daemon that periodically runs tasks at various
intervals according to their potential impact on the system and
need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a one-shot “fix stuff” command that can be run from cron or
otherwise scheduled or executed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a daemon or one-shot command that purely audits potential
problems, but makes no changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new config section of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[audit]&lt;/span&gt;&lt;/code&gt; would be added with timers and
default values for each task.&lt;/p&gt;
&lt;p&gt;Current heal/sync/fix/cleanup tasks we have that could be integrated:&lt;/p&gt;
&lt;section id="heal-allocations"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_allocations&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks the consistency of allocations in Placement for
instances in Nova. It has a runtime performance impact on both
Placement and the Nova database. Many instances means this should
probably check one instance per cycle, but potentially a short cycle
time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="audit-allocations"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;audit_allocations&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks for orphaned allocations in Placement for instances in
Nova and will delete them if specified by the configuration.
It has a runtime performance impact on both Placement and the Nova
database. Many instances means this should probably check one instance
per cycle, but potentially a short cycle time.&lt;/p&gt;
&lt;p&gt;Today, the command is named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;placement&lt;/span&gt; &lt;span class="pre"&gt;audit&lt;/span&gt;&lt;/code&gt; but it
might be a good idea to name it more specifically inside the context of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt; command and service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="sync-aggregates"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sync_aggregates&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks that host aggregates match between Nova and
Placement. It is required for some scheduler activities, but not all
cases. It has a runtime performance impact on both Placement and the
Nova database. Many hosts means this should probably check one
aggregate per cycle. Aggregates generally change infrequently, so a
long cycle time of an hour or more is probably reasonable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="map-instances"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;map_instances&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks that instances have a suitable mapping to a cell. It
has a runtime performance impact on the Nova database. Many instances
means this should probably check one instance per cycle, with a
relatively short cycle time. It may also be better to check one cell
at a time, very infrequently such as once per day.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="discover-hosts"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;discover_hosts&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task ensures that newly-registered hypervisor hosts are mapped to
the appropriate cell. This has a runtime impact on the Nova database,
but there is an efficient way to query for unmapped hosts, so this can
run relatively frequently, such as every ten minutes.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;There is already a mechanism by which to run this
periodically in the scheduler service, which should be
deprecated and replaced by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="archive-deleted-rows"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task archives deleted data from the main database tables into the
shadow tables. It has a runtime performance impact on the Nova
database, both negative (while running) and positive (after
running). Some people never run this, so a cycle time of once per day
or week should be fine. This also needs a parameter to limit the scope
of archived changes to a date range, defaulting to some multiple of
the cycle time.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This (and others) may need a configuration element to
control its execution only between certain hours or days.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="purge"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;purge&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task removes data from the shadow tables entirely. It has a
runtime performance impact on the Nova database, but it is just
deleting data from tables accessed only during the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt; operation. In reality, this should probably
be run directly after the archival process, potentially with a
different age scope.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="heal-instance-mappings-proposed"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_instance_mappings&lt;/span&gt;&lt;/code&gt; (proposed)&lt;/h3&gt;
&lt;p&gt;This task scans for orphaned instance mappings in the API database
that have no build request or matching instance in a cell. It has a
runtime performance impact on the Nova API and cell databases, but
only looks for mappings with no cell id. It is bounded by the number
of in-flight instance builds plus the number of orphans, which should
be small. Thus it should be fine to run this relatively frequently,
such as every ten minutes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could obviously do nothing. People are managing the complexity
today, so we could simply choose to let them continue.&lt;/p&gt;
&lt;p&gt;We could eliminate the daemon and scheduling nature of the proposal
and just provide a very unified interface to running these commands –
a single place to find all the periodic maintenance tasks separate
from the setup sort of things that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;We could integrate this into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; itself, under a
“maintenance” subcommand or similar.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None. You could argue that notifications sent about audit activity
would be useful, but doing so would require more setup and
configuration of this utility, as well as connectivity and credentials
to the message bus. We could implement that later if there is a need.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be some runtime performance impact due to the background
nature of the audit and any cleanup that happens. Mitigation is to not
run it, tune the intervals to be longer, or run it in single-shot mode
when desired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will have to learn about and deploy a new
command/service. This will hopefully be completely offeset by the
reduced complexity of managing and maintaining Nova in the longer
term.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New maintenance tasks that are added will need to be done in an
idempotent and efficient way and according to whatever interface for
these commands is defined.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new binary will be added, which will have some impact on
upgrades. Any existing periodic maintenance jobs that call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;
for various tasks will need to convert over to the new command. The
interfaces we have for existing things in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; can be
deprecated but maintained for an extended period to avoid breaking
existing deployments.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Specific tasks like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt; may make
sense to continue to exist in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; as well.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt; command and define scheduling
mechanisms and internal interfaces.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the new config section and items.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement connectors to integrate the existing tasks we have into
the new command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-next&lt;/span&gt;&lt;/code&gt; job to run the audit command in single-shot
mode after the tempest run, ideally removing the existing
archive/purge invocation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional testing of the daemon and internal architecture,
and the continued requirement for testing of the actual tasks.  A
single-shot run in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-next&lt;/span&gt;&lt;/code&gt; job as we currently do today for
archive/purge.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operator documentation about the new command, how to deploy it, and
per-knob documentation about the impacts and suggested intervals.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Proposed new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_instance_mappings&lt;/span&gt;&lt;/code&gt; command for Ussuri: &lt;a class="reference external" href="https://review.opendev.org/#/c/655908/"&gt;https://review.opendev.org/#/c/655908/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Commands in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html"&gt;https://docs.openstack.org/nova/latest/cli/nova-manage.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed and added the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;audit_allocations&lt;/span&gt;&lt;/code&gt; task to include
the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;placement&lt;/span&gt; &lt;span class="pre"&gt;audit&lt;/span&gt;&lt;/code&gt; functionality in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 12 Jul 2021 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas"&gt;https://opendev.org/openstack/nova/src/branch/master/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sat, 10 Jul 2021 00:00:00 </pubDate></item><item><title>Guest CPU selection with hypervisor consideration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/cpu-selection-with-hypervisor-consideration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cpu-selection-with-hypervisor-consideration"&gt;https://blueprints.launchpad.net/nova/+spec/cpu-selection-with-hypervisor-consideration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make Nova’s guest CPU selection approach more effective and reliable by
introducing two new QEMU- and libvirt-based CPU configuration APIs:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt;.  These new
APIs are more “hypervisor-literate” compared to the existing libvirt
APIs that Nova uses.  As in, the new APIs take into account what the
“host hypervisor” (meaning: KVM, QEMU, and what libvirt knows about the
host) is capable of.&lt;/p&gt;
&lt;p&gt;Taking advantage of these newer APIs will allow Nova to make more
well-informed decisions when determining CPU models that are compatible
across different hosts.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current guest CPU config libvirt APIs that Nova uses,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt;, are “not very useful” (quoting
the cover letter &lt;a class="footnote-reference brackets" href="#id5" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; of the libvirt patch series that introduced the
newer APIs), because they don’t consider the capabilities of the “host
hypervisor” (KVM, QEMU and details libvirt knows about the host).  More
concretely, with the existing APIs, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt;, there is no way to ask if a given CPU model plus CPU
flags combination is supported by KVM and a specific QEMU binary on the
host.&lt;/p&gt;
&lt;p&gt;For example, today operators have to be careful about how they configure
the libvirt driver with regard to &lt;cite&gt;cpu_model&lt;/cite&gt; and
&lt;cite&gt;cpu_model_extra_flags&lt;/cite&gt;, because the wrong combination (e.g. an invalid
CPU flag that is not supported by the host hypervisor) can lead to an
instance failing to spawn.  I.e. operators have to manually validate the
extra CPU flags they’re supplying to Nova are actually supported by the
given compute host.&lt;/p&gt;
&lt;p&gt;This spec will allow Nova &lt;a class="footnote-reference brackets" href="#id6" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to do fine-grained validation of a given
CPU model plus CPU flags against a specific QEMU binary (and KVM) to
allow well-informed guest CPU configuration decisions.  And taking
advantage of the said two new libvirt APIs will also allow computing a
more accurate baseline guest CPU that permits live migration across
several compute nodes.  And provides a clearer picture of what CPU
features are required to get mitigations from Meltdown and Spectre.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;By taking advantage of the two CPU configuration APIs,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt;, Nova will
now be able to make meaningful decisions when determining guest CPU
models and their features:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;While determining guest CPU models, Nova can take into account
several other aspects, e.g. the type of virtualization (pure
emulation vs. hardware-accelerated), QEMU binary’s capabilities,
guest machine type, and CPU architcture to construct a
better-informed guest CPU.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova will be able to do more fine-grained validation of CPU models and
flags, i.e. answer questions like: “Is the combination of Intel’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IvyBridge&lt;/span&gt;&lt;/code&gt; CPU model plus the CPU flags &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pcid&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ssbd&lt;/span&gt;&lt;/code&gt;
supported by the host hypervisor?”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Armed with the above two points, Nova will also be positioned to
better report more accurate CPU traits.  (I.e. improve the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_cpu_traits()&lt;/span&gt;&lt;/code&gt; method.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operators can get a more accurate view on what guest CPU models and
features their guests can realistically expect.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Make Nova’s CPU selection strategy more effective by taking advantage of
the two new libvirt APIs: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.  These APIs provide more useful ways to
determine compatible models among CPU variants, and elimiates bugs in
the older CPU config libvirt APIs along the way.&lt;/p&gt;
&lt;p&gt;With this change, the libvirt driver will automatically validate if a
certain combination of CPU model + flags can work on a given compute
host — e.g. Nova will now be able to answer: “Is this combination of
‘IvyBridge’ plus CPU flags ‘pcid’ &amp;amp; ‘pdpe1gb’ supported by KVM, QEMU and
libvirt on the host?”.  And, if the given combination of CPU model plus
flags are invalid, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; service will refuse to start,
with an actionable log message.&lt;/p&gt;
&lt;p&gt;This will let the operator set the CPU model plus flags, and let Nova
handle the validation.&lt;/p&gt;
&lt;p&gt;A quick description of the two APIs:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Purpose: This API computes the most feature-rich “baseline” CPU (which
includes CPU model plus additional features) that is (a) compatible with
all given host CPUs (as described in an XML document), so that one can
live migrate across the said hosts; and (b) is supported by the host
hypervisor.  It is a more useful version of the older &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselinCPU()&lt;/span&gt;&lt;/code&gt;,
which does not consider any hypervisor capabilities when computing the
baseline CPU.&lt;/p&gt;
&lt;p&gt;A comparison of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineHypervisorCPU()&lt;/span&gt;&lt;/code&gt; APIs,
in terms of what parameters they take into account:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+-----------+--------------------+-----------------------------+
|           | baselineCPU()      | baselineHypervisorCPU()     |
+-----------+--------------------+-----------------------------+
|           | XML document       | XML document describing     |
|           | describing one     | one or more host CPUs       |
|           | or more host CPUs  |                             |
|           +--------------------+-----------------------------+
|           |                    | path to the QEMU binary     |
|           |                    +-----------------------------+
|Parameters |                    | the type of virtualization  |
|           |                    | (e.g. KVM, QEMU)            |
|           |                    +-----------------------------+
|           |                    | guest machine type          |
|           |                    +-----------------------------+
|           |                    | CPU architecture            |
+-----------+--------------------+-----------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Purpose: This API compares a given CPU description with the CPU
capabilities the host hypervisor is able to provide.  It is a more
useful version of the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt;, which compares the CPU
definition with the host CPU without considering any specific hypervisor
and its abilities.&lt;/p&gt;
&lt;p&gt;A comparison of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareHypervisorCPU()&lt;/span&gt;&lt;/code&gt; APIs, in
terms of what parameters they take into account:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+-----------+--------------------+-----------------------------+
|           | compareCPU()       | compareHypervisorCPU()      |
+-----------+--------------------+-----------------------------+
|           | XML describing the | XML describing the CPU      |
|           | CPU to be compared | to be compared              |
|           +--------------------+-----------------------------+
|           |                    | path to the QEMU binary     |
|           |                    +-----------------------------+
|Parameters |                    | the type of virtualization  |
|           |                    | (e.g. KVM, QEMU)            |
|           |                    +-----------------------------+
|           |                    | guest machine type          |
|           |                    +-----------------------------+
|           |                    | CPU architecture            |
+-----------+--------------------+-----------------------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;By making Nova use the above two APIs, it can now do more advanced
validation of CPU model plus flags compatibility, which ensures an
instance cannot be launched with CPU features that don’t exist in the
host CPU.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could just “stay put” and keep chugging along with the existing older
libvirt APIs, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;baselineCPU()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compareCPU()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But that would be doing a disservice to our users, as we have more
reliable APIs that provide a more well-informed guest CPU configuration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This implicitly improves security – as in, with these new APIs, you
should be able to get a better sense of what CPU features are required
to get mitigations from Meltdown and Spectre.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The following libvirt and QEMU versions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt;: QEMU &amp;gt;= 2.9, libvirt &amp;gt;= 4.4.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;s390x&lt;/span&gt;&lt;/code&gt;: QEMU &amp;gt;= 2.9, libvirt work is actively in progress
upstream &lt;a class="footnote-reference brackets" href="#id8" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt;, users should have the minimum-required verisons of
libvirt and QEMU to be 4.4.0 and 2.9, respectively.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;kashyapc&amp;gt;, &amp;lt;chengsheng&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce a Nova wrapper method, baseline_hypervisor_cpu(), for
libvirt’s baselineHypervisorCPU() API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a Nova wrapper method, compare_hypervisor_cpu(), for
libvirt’s compareHypervisorCPU() API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rework the _get_guest_cpu_model_config() method in the libvirt
driver to take advantage of the fine-grained validation of CPU model
plus features (against a given QEMU binary), if available on the given
compute host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rewrite the _compare_cpu() method’s the logic in the libvirt driver to
take advantage of compareHypervisorCPU().  (While at it, rename it to
_compare_hypervisor_cpu().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the check_can_live_migrate_destination() method in the libvirt
driver to use the newer wrapper API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the get_capabilities() method in nova/virt/libvirt/host.py to
take advantage of baseline_hypervisor_cpu(), if available on the given
compute host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This can be done separately, but noting for completeness’ sake: Update
_get_cpu_traits() method to use baselineHypervisorCPU().  (Support for
s390x shouldn’t be a blocker to get started on this.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This is not a strict dependency, but as noted earlier, support for s390x
for libvirt’s compareHypervisorCPU() and baselineHypervisorCPU() is
still in progress upstream.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce “fake libvirt” methods for baselineHypervisorCPU() and
compareHypervisorCPU() APIs with minimum-required functionanlity
(because duplicating libvirt’s logic is complicated and doesn’t add
much value to replicate it).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Potentially a couple of functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Consider adding a section in the Nova admin guide on how the newer APIs
allow more reliable guest CPU configuration.  Also note explicitly that
we recommend to stick to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host-model&lt;/span&gt;&lt;/code&gt;, which is the the default CPU
mode for the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;“New CPU related APIs”
– &lt;a class="reference external" href="https://www.redhat.com/archives/libvir-list/2018-May/msg01204.html"&gt;https://www.redhat.com/archives/libvir-list/2018-May/msg01204.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;“[RFE] Fine-grained API to validate if a given CPU model and flags
are supported by QEMU / KVM”
– &lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1559832"&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1559832&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Refer to slide-28 here:
&lt;a class="reference external" href="https://kashyapc.fedorapeople.org/Effective-Virtual-CPU-Configuration-in-Nova-Berlin2018.pdf"&gt;https://kashyapc.fedorapeople.org/Effective-Virtual-CPU-Configuration-in-Nova-Berlin2018.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;libvirt work for s390x:
&lt;a class="reference external" href="https://www.redhat.com/archives/libvir-list/2019-January/msg00310.html"&gt;https://www.redhat.com/archives/libvir-list/2019-January/msg00310.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Jul 2021 00:00:00 </pubDate></item><item><title>Add no user token auth when get Cyborg client</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/cyborg-admin-user-client.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cyborg-admin-user-client"&gt;https://blueprints.launchpad.net/nova/+spec/cyborg-admin-user-client&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add support for cyborg service credentials to create cyborg admin client
instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Today, if VM hard reboot is triggered by resume_guests_state_on_host_boot=True
during nova-compute start, nova uses a non admin context to retrieve ARQs.
Nova should use the cyborg service token to make such query instead.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, when I reboot a host and have
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]/resume_guests_state_on_host_boot=True&lt;/span&gt;&lt;/code&gt;
I would like my cyborg instance to retain access to their assigned
accelerators.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add Cyborg auth configuration in nova.conf.
Add support for create a cyborg admin client when no user token is present.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Introduce user information to obtain authentication, which will make Nova
and Cyborg interaction less secure since we will now use a higher
privileged token and the cyborg admin password will now be present on
the compute node.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will have to add Cyborg auth with user and password configuration
in nova-cpu.conf for nova-compute service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;songwenping&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;songwenping&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Register Cyborg group conf.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend nova.accelerator.cyborg.get_client to create admin clients.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Fix old unit and functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 09 Jun 2021 00:00:00 </pubDate></item><item><title>Boot a VM with an unaddressed port</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/vm-boot-with-unaddressed-port.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/boot-vm-with-unaddressed-port"&gt;https://blueprints.launchpad.net/nova/+spec/boot-vm-with-unaddressed-port&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint aims to allow a VM to boot with an attached port without any IP
assigned.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Neutron permits users to create a port assigned to a network with
corresponding subnets and IP pools, without an IP address assigned. However
Nova only allows users to create a VM with a port without an IP only if this
address assignment is deferred; that means that the port is expected to have
an IP address but Neutron deferred the IP allocation until the host to which
the port will be bound is populated.&lt;/p&gt;
&lt;p&gt;However, there are some network applications (e.g.: service function
forwarding, service function classifier, CMTS) that often forward traffic that
is not intended for them. Those applications have an interface without a
primary L3 address which may be receiving traffic for so many disparate
addresses that configuring all of them in Neutron is a burden.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;A typical use case is when a user wishes to deploy a VM which accepts traffic
that is neither IPv4 nor IPv6 in nature. For example, a CMTS (Cable Modem
Termination System).&lt;/p&gt;
&lt;p&gt;Another use case could be a VM that accepts traffic for a very wide address
range (for either forwarding or termination) and where the port has no primary
address. In such cases, the VM is not a conventional application VM.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to allow to spawn a VM with a manually created port without
IP address assignation.&lt;/p&gt;
&lt;p&gt;When a port in Neutron is created with the option “–no-fixed-ip”, the port
parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; will be populated with “none” &lt;a class="footnote-reference brackets" href="#id9" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This way
Neutron marks a port not to have an IP address. Nova, during the instance
creation, validates the build options; in particular the ports provided to be
bound to this new VM. To be able to use an unaddressed port, Nova needs to
modify the logic where IP assignation is tested &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;As commented in the use cases, some applications will accept traffic that is
neither IPv4 nor IPv6. Having an IP address is irrelevant on those ports but
doesn’t affect the application.&lt;/p&gt;
&lt;p&gt;In other cases, like in a routing application, there is no alternative. It’s
not possible to define in Neutron all the possible IP addresses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;The Neutron port contains the information needed in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt;
parameter and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;connectivity&lt;/span&gt;&lt;/code&gt; parameter inside the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:vif_details&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Those ports without an assigned IP don’t work with the Neutron in-tree
firewalls (iptables and OVS Open Flows based). Both firewalls will filter the
egress and the ingress traffic depending on several parameters, including the
IP address. To let the traffic come into the virtual interface, the firewall
should be disabled in the compute node hosting the VM. This mandatory
configuration will be documented.&lt;/p&gt;
&lt;p&gt;Once the Nova feature is implemented and tested, a new feature will be
requested to Neutron, in order to allow those ports without an IP address to
work correctly with the in-tree firewalls.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;To be able to remotely access to the created VM, the user needs to add an
addressed port to the VM. This “management” port must have an IP address.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Some L2 driver, like “l2-pop”, may have problems when dealing with this kind of
port because they use proxy ARP to answer ARP requests from known IP address.&lt;/p&gt;
&lt;p&gt;The [“novnc”] service won’t work with a port without an IP address. This is why
it’s recommended to create a VM with at least one management port, with an
assigned IP address.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Rodolfo Alonso &amp;lt;rodolfo-alonso-hernandez&amp;gt; (&lt;a class="reference external" href="mailto:ralonsoh%40redhat.com"&gt;ralonsoh&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Change the logic of how the IP assignation is tested &lt;a class="footnote-reference brackets" href="#id10" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the tempest test described.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new Neutron feature request to change the in-tree firewalls to work
correctly with those ports without IP address assigned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None. The necessary work in neutron has already been accomplished via two
specs. The main neutron change was allowing for the creation of an unaddressed
port and mark it, by populating the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt; parameter with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt;.
This was covered by the “Allow vm to boot without l3 address(subnet)” &lt;a class="footnote-reference brackets" href="#id12" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec. The changes introduced as part of the “Port binding event extended
information for Nova” &lt;a class="footnote-reference brackets" href="#id11" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec means neutron will now provide the type of
back-end to which the port is bound, with the parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;connectivity&lt;/span&gt;&lt;/code&gt;,
included now in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:vif_details&lt;/span&gt;&lt;/code&gt;. Nova can determine whether a given
driver back-end has “l2” connectivity and, if so, know that a port without an
IP address can be assigned to a virtual machine.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Apart from the needed functional and unit testing, a tempest test could cover
this feature. This tempest test will spawn three VMs, each one with a
management port, to be able to SSH to the machine. Then two traffic networks
will be created, net1 and net2.&lt;/p&gt;
&lt;p&gt;The first machine will have a port, with an IP assigned, connected to net1.
The third machine will have a port, with an IP assigned, connected to net2.
And finally, the second machine, in the middle of the first and the third one,
with be connected to net1 and net2 with two ports without an IP address.
The second machine will have the needed iptables rules to NAT the traffic
between the first VM and the third VM port.&lt;/p&gt;
&lt;p&gt;Both the first and the third machine will need a manual entry in the ARP table
to force the traffic going out trough the traffic port.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make a reference of this feature in the user document “Launch instances”
&lt;a class="footnote-reference brackets" href="#id13" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/blob/stable/rocky/releasenotes/notes/add-port-ip-allocation-attr-294a580641998240.yaml"&gt;https://github.com/openstack/neutron/blob/stable/rocky/releasenotes/notes/add-port-ip-allocation-attr-294a580641998240.yaml&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/blob/stable/rocky/neutron/db/db_base_plugin_v2.py#L1323"&gt;https://github.com/openstack/neutron/blob/stable/rocky/neutron/db/db_base_plugin_v2.py#L1323&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/stable/rocky/nova/network/neutronv2/api.py#L2078-L2086"&gt;https://github.com/openstack/nova/blob/stable/rocky/nova/network/neutronv2/api.py#L2078-L2086&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/645173/"&gt;https://review.opendev.org/#/c/645173/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/neutron/+spec/vm-without-l3-address"&gt;https://blueprints.launchpad.net/neutron/+spec/vm-without-l3-address&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/stable/rocky/doc/source/user/launch-instances.rst"&gt;https://github.com/openstack/nova/blob/stable/rocky/doc/source/user/launch-instances.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id14"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 26 May 2021 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/nova/tree/nova/api/openstack/compute/schemas"&gt;http://git.openstack.org/cgit/openstack/nova/tree/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;p&gt;Consider creating an ordering of patches, that allows gradually merging
instead of the need to merge them all at once. For example if you are
introducing a feature that requires implementation changes in multiple VM
lifecycle operations then first add a step that rejects all the not yet
supported actions with a HTTP 400 Bad Request. The error should explain that
the &amp;lt;operation&amp;gt; is not supported with &amp;lt;feature&amp;gt; at this time. Then gradually
remove the limitation as you progress with the implementation. This way we can
merge your changes gradually and regardless when the feature freeze hit we can
be sure that the system is consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 26 May 2021 00:00:00 </pubDate></item><item><title>Allow Project admin to list allowed hypervisors</title><link>https://specs.openstack.org/openstack/nova-specs/specs/yoga/approved/allow-project-admin-list-hypervisors.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/allow-project-admin-list-hypervisors"&gt;https://blueprints.launchpad.net/nova/+spec/allow-project-admin-list-hypervisors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow Project admin to get the allowed hypervisors info so that
they can create a server to specify the host in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Project admin can currently create a server on a specific hypervisor (via host
in the availability_zone field). However, project admin is not allowed to
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/policies/hypervisors.py#L37"&gt;list the hypervisors&lt;/a&gt; On the other hand, only system admins or system
readers can list hypervisors, but they cannot create a server on the project’s
behalf because there is no way to pass the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/api/openstack/compute/schemas/servers.py#L149"&gt;project_id in POST /servers API&lt;/a&gt;.
This way, we make ‘POST /servers with specific host’ unusable unless the user
gives extra token permission to the project admin or system users.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user (project admin currently and project manager in new RBAC), I should
be able to create the server on specific host which is assigned in that
project.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Below are the three proposed changes:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-hypervisors&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;
&lt;p&gt;Allow project admin to list &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;state&lt;/span&gt;&lt;/code&gt;, and, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt;
of the hypervisors they are assigned to. That will be retrieved from
aggregate metadata info (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_tenant_id&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If the requested project is in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_tenant_id&lt;/span&gt;&lt;/code&gt; then that host info will
be listed for project admin. If no project is listed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_tenant_id&lt;/span&gt;&lt;/code&gt;
then return an empty list. Only below hypervisors’ fields will be returned
for project admin, and the rest of the fields will be returned with value
as None.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;uuid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;status&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new API policy will be introduced to switch the above behaviour to return
the complete list of hypervisors info to allowed users.&lt;/p&gt;
&lt;p&gt;No change in returning the hypervisors list for System scoped users.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API will start accepting hypervisor uuid in request field
to boot the server on that hypervisor. The existing field
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; is used to pass the hypervisor name and we will not
change that for existing use case. We will add a new field
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_uuid&lt;/span&gt;&lt;/code&gt; in request so that user can pass hypervisor uuid. The
hypervisor uuid will be used to boot the server for for host with scheduler
run case.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the legacy hack of passing the host and node in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt;
request field. This will be removed for newer microversion only and keep it
same for older microversion.&lt;/p&gt;
&lt;p&gt;This is legacy hack to force the server boot on requested host and node.
This one - &lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561&lt;/a&gt;
Removing this legacy hack will standaradize the ‘server boot on requested
host’ request.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;System users knowing the hypervisor info can switch to the project admin token
and boot server on specific host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This change will be done with a microversion bump.&lt;/p&gt;
&lt;p&gt;Below are the two APIs that will be changed:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-hypervisors&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Allow policy ‘os_compute_api:os-hypervisors:list’ to project admin also
(scope to system and project).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the requester is system user or project admin (via request context’s
system_scope). For system users no change in API from what we have currently.
For project admin, return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uuid&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;state&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt; of
those hosts which are assigned to that project, and the rest of the fields
will be returned with value as None.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"hypervisors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"hypervisor_hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1bb62a04-c576-402c-8147-9e89757a09e3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"enabled"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"hypervisors_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API will start accepting hypervisor uuid in request field
to boot the server on that hypervisor. We will add a new  field
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_uuid&lt;/span&gt;&lt;/code&gt; in create server request so that user can pass uuid.
The hypervisor uuid will be used to boot the server for host with scheduler
run case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the legacy hack of passing the host and node in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt;
request field. For older microversions, it will keep working as it is working
currently. With this new microversion, only a valid AZ will be accepted in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt; field otherwise 404. Basically removing this legacy
hack - &lt;a class="reference external" href="https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561"&gt;https://github.com/openstack/nova/blob/e28afc564700a1a35e3bf0269687d5734251b88a/nova/compute/api.py#L555-L561&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None. Already assigned host uuid name will be listed to project admin also.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The nova api-ref will updated to reflect the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Upgrade notes will be added for the new workflow of boot server on
specific host.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API changes with microversion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing for the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit or functional testing for API change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest test to boot server with hypervisor uuid.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The api-ref will be updated to reflect the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-xena-ptg"&gt;https://etherpad.opendev.org/p/nova-xena-ptg&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova-specs/+/779821"&gt;https://review.opendev.org/c/openstack/nova-specs/+/779821&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/policies/servers.py#L179"&gt;https://github.com/openstack/nova/blob/b0cd985f0c09088098f74cc0cb1df616cc0ef12b/nova/policies/servers.py#L179&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Yoga&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 25 May 2021 00:00:00 </pubDate></item><item><title>QoS minimum guaranteed packet rate</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/qos-minimum-guaranteed-packet-rate.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/qos-minimum-guaranteed-packet-rate"&gt;https://blueprints.launchpad.net/nova/+spec/qos-minimum-guaranteed-packet-rate&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Similarly to how bandwidth can be a limiting factor of a network interface,
packet processing capacity tend to be a limiting factor of the soft switching
solutions like OVS. In the same time certain applications are dependent on not
just guaranteed bandwidth but also on guaranteed packet rate to function
properly. OpenStack already supports bandwidth guarantees via the
&lt;a class="reference external" href="https://docs.openstack.org/api-ref/network/v2/?expanded=#qos-minimum-bandwidth-rules"&gt;minimum bandwidth QoS policy rules&lt;/a&gt;. This specification is aiming for adding
support for a similar minimum packet rate QoS policy rule.&lt;/p&gt;
&lt;p&gt;To add support for the new QoS rule type both Neutron and Nova needs to be
extended. This specification covers the high level description of these
impacts, the interaction between Neutron, Placement and Nova. And have
the details of the Nova specific changes necessary. For the detailed
description of the Neutron impact please see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;OpenStack needs to provide support for minimum packet rate guarantees on
Neutron ports via a new QoS policy rule type.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;I as an administrator want to define the maximum packet rate, in kilo packet
per second (kpps), my OVS soft switch capable of handle per compute node, so
that I can avoid overload on OVS.&lt;/p&gt;
&lt;p&gt;I as an end user want to define the minimum packet rate, in kilo packet per
second (kpps) a Neutron port needs to provide to my Nova server, so that my
application using the port can work as expected.&lt;/p&gt;
&lt;p&gt;I as an administrator want to get a Nova server with such ports placed on a
compute node that can still provide the requested minimum packet rate for the
Neutron port so that the application will get what it requested.&lt;/p&gt;
&lt;p&gt;I as an administrator want that the nova server lifecycle operations are
rejected in case the requested minimum packet rate guarantee of the Neutron
ports of the server cannot be fulfilled on any otherwise eligible compute
nodes, so that the OVS overload is avoided and application guarantees are kept.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The whole solution is very similar and the proposed implementation heavily
rely on the already implemented &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/stein/implemented/bandwidth-resource-provider.html"&gt;qos guaranteed minimum bandwidth feature&lt;/a&gt;.&lt;/p&gt;
&lt;section id="new-resources"&gt;
&lt;h3&gt;New resources&lt;/h3&gt;
&lt;p&gt;The solution needs to differentiate between two deployment scenarios.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The packet processing functionality is implemented on a shared hardware
(e.g. on the same compute host CPUs) and therefore both ingress and egress
queues are handled by the same hardware resources. This is the case in the
non-hardware-offloaded OVS deployments. In this scenario OVS represents a
single packet processing resource pool. Which can be represented with a
single new resource class, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The packet processing functionality is implemented in a specialized hardware
where the ingress and egress queues are processed by independent
hardware resources. This is the case for hardware-offloaded OVS. In this
scenario a single OVS has two independent resource pools one for the
incoming packets and one for the outgoing packets. Therefore these needs to
be represented with two new resource classes
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_EGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_IGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;1 kilo packet means 1000 packets in the context of packet rate resource.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;These new resource classes needs to be added to Placement’s os-resource-classes
library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="packet-processing-resource-inventory"&gt;
&lt;h3&gt;Packet processing resource inventory&lt;/h3&gt;
&lt;p&gt;The bandwidth resources are modelled on the OVS physnet bridges as each bridge
is connected to a specific physical NIC that provides the bandwidth resource.
As the packet processing resource is provided by the OVS service itself
therefore the packet processing resource needs to be modeled on an entity that
is global for the whole OVS service. Today we have such entity, the Neutron OVS
agent itself. This assumes that one Neutron OVS agent only handles one OVS
which is true today. We think this assumption is strong one. If later on two
vswitches are needed on the same compute host then we think it is easier to
duplicate the agents handling them separately than enhancing the current agent
to handle two switches.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="resource-inventory-reporting"&gt;
&lt;h3&gt;Resource inventory reporting&lt;/h3&gt;
&lt;p&gt;For details of these Neutron changes please see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Neutron OVS agent needs to provide configuration options for the
administrator to define the maximum packet processing capacity of the OVS
per compute node. Depending on the deployment scenario this might mean a
single directionless inventory value, or two direction aware values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron agent needs to communicate the configured capacity to the Neutron
server via the agent hearth beat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron server needs to report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_[E|I]GR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; resource inventory on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Open&lt;/span&gt; &lt;span class="pre"&gt;vSwitch&lt;/span&gt; &lt;span class="pre"&gt;agent&lt;/span&gt;&lt;/code&gt; resource provider to Placement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="requesting-minimum-packet-rate-guarantees"&gt;
&lt;h3&gt;Requesting minimum packet rate guarantees&lt;/h3&gt;
&lt;p&gt;For details of these Neutron changes please see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Neutron QoS API needs to be extended with the new minimum packet rate QoS rule
type. The rules of this type need to be persisted in the neutron DB similarly
to the other QoS rules.&lt;/p&gt;
&lt;p&gt;To support the two different OVS deployment scenario we need two sets of new
minimum guaranteed QoS rule types. One which is directionless to support the
case when the resource is also directionless. And two other that are direction
aware to support the other deployment case where the pps resource are also
direction aware.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="nova-servers-with-the-new-qos-policies"&gt;
&lt;h3&gt;Nova servers with the new QoS policies&lt;/h3&gt;
&lt;p&gt;Today Neutron expresses the resource needs of a port via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field. The value of this field is intended to communicate
the resource needs in a generic, machine readable way. Nova and
(and indirectly Placement) uses this during the scheduling of the server to
decide which compute host can fulfill the overall resource needs of the server
including the ports of the server. So far the port can only have bandwidth
resource request.&lt;/p&gt;
&lt;p&gt;To support the new packet rate resource Neutron API needs to be changed so that
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; read only field of the port could contain more than
one group of requested resources and required traits. Today the content of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; is translated to a single, named Placement request group
during scheduling. As a single port can have both bandwidth and packet rate QoS
applied and because bandwidth is allocated from the bridge / physical device
while the packet rate resource is allocated from the whole OVS instance the two
groups of resources need to be requested separately. The technical reason to
this is that a single named resource request group is always allocated from a
single resource provider in Placement. So if bandwidth and packet rate does not
need to come from the same resource provider then they should be requested in
different resource request groups.&lt;/p&gt;
&lt;p&gt;The new format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"request_groups"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="s2"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_VNIC_TYPE&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;NET_PACKET_RATE_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;GR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="n"&gt;requested&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;QoS&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="s2"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_PHYSNET_&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_VNIC_TYPE&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NET_BW_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;GR_KILOBIT_PER_SEC&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;requested&lt;/span&gt; &lt;span class="n"&gt;bandwidth&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;the&lt;/span&gt; &lt;span class="n"&gt;QoS&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"same_subtree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;above&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;above&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For the reasoning why we need this format see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Neutron port binding API needs to be extended. Today the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation&lt;/span&gt;&lt;/code&gt;
key in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile&lt;/span&gt;&lt;/code&gt; of the port is used by Nova to communicate the
UUID of the resource provider from which the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; of the port
is fulfilled from. This is then used by the Neutron’s port binding logic to
bind the port to the same physical device the Placement resource is allocated
from. Now that a port can request resources from more than one placement
resource providers a single UUID is not enough to communicate where those
resources are allocated from. Nova needs to provide a mapping instead that
describes which set of resource, a.k.a which request group, is fulfilled from
which resource provider in placement.&lt;/p&gt;
&lt;p&gt;For the details of the new structures see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="adapting-nova-to-the-neutron-changes"&gt;
&lt;h3&gt;Adapting Nova to the Neutron changes&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova needs to adapt to the changes in the structure and semantics of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field of the neutron port. Today Nova translates this
field to a single named resource request group. After the Neutron changes
this field will communicate a list of such request groups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova also assumes today that a port only allocates resource from a single
resource provider. This assumption needs to be removed and the implementation
needs to support a list of such resource providers. Nova can still assume
that a single placement request group is fulfilled by a single resource
provider as that is an unchanged Placement behavior.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These Nova changes needs to be applied to every code path in Nova that results
in a new scheduling attempt including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;server create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;migrate, resize, evacuate, live-migrate, unshelve after shelve-offload&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;interface attach and detach&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="what-is-out-of-scope"&gt;
&lt;h3&gt;What is out of scope&lt;/h3&gt;
&lt;p&gt;Supporting minimum packet rate policy for other than OVS backends are out of
scope but can be handled later with a similar proposal.&lt;/p&gt;
&lt;p&gt;This spec only aiming to give scheduling time guarantees for the packet
rate. The data plane enforcement of the new policy is out of scope. When the
&lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1912460"&gt;packet rate limit policy rule&lt;/a&gt; feature is implemented then a basic data plane
enforcement can be applied by adding both minimum and maximum packet rate QoS
rules to the same QoS policy where maximum limit is set to be equal to the
minimum guarantee.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="id1"&gt;
&lt;h4&gt;Packet processing resource inventory&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Alternatively&lt;/em&gt; it was suggested to define the packet processing inventory
on the OVS bridge level. The big advantage of having the pps resource
represented on the OVS bridge, on the same place as the bandwidth resource, is
that it would simplify the overall design. It would means that we could still
keep the assumption that the resource request of the port is always fulfilled
from a single resource provider. Therefore the format of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile.allocation&lt;/span&gt;&lt;/code&gt; does not need to
change. However there are a list of counter arguments against this direction:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If we define packet processing capacity on the bridges then if there are
multiple bridges then the overall packet processing capacity of the whole OVS
would need to be statically split between the bridges, while the actual
resource usage of OVS are not split in that way in reality.
Configuration with multiple bridges are possible today, even in the
frequently used case of having one phynet bridge for VLAN traffic and one
tunneling bridge for the VXLAN traffic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In case of bandwidth the actual resource is behind the physnet bridge, the
physical interface the bridge is connected to, so the resource is dedicated
to the bridge. But in case of packet processing the actual resource is not at
all dedicated to the given bridge but it is dedicated to the whole OVS
instance. So while we can assign a portion of the overall resource to the
bridge this assignment would never represent the reality well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Traffic between the VMs on the same host does not flow through the physnet or
tunneling bridges but it does impact the capacity of the OVS on the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While the currently proposed design change is significant it makes the
solution more future proof. E.g. for the case when the IP pool resource
handling will be refactored to use the port’s resource_request then we anyhow
need to be able to handle another resource provider that will not be the same
as any of the existing ones as the IP addresses are shared resource between
multiple host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Another alternative&lt;/em&gt; would be to represent the packet processing capacity on a
new provider that maps to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;br-int&lt;/span&gt;&lt;/code&gt; the OVS integration bridge where the VMs
are plugged. This have the benefit that the resource inventory would be global
on OVS instance level and also it would clean up some of the confusion created
by having a separate OVS Agent RP. Moving further we could even consider
dropping the Agent RP altogether and only representing the bridge hierarchy in
Placement with the resource provider hierarchy. Logically it is not different
from that we rename today’s OVS Agent RP to br-int RP. However &lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2021-05-21.log.html#t2021-05-21T10:33:22"&gt;we agreed&lt;/a&gt;
that keep this as a future exercise if and when more OVS instances would be
needed per OVS agent.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="id2"&gt;
&lt;h4&gt;Requesting minimum packet rate guarantees&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Alternatively&lt;/em&gt; it was suggested that it would be enough to have a single set
of direction aware QoS rule types. Then in case of the normal OVS deployment
scenario, where the resource is directionless, the resource requests from the
direction aware QoS rules could be added together before matched against the
single directionless resource inventory. Neutron would be able to differentiate
between the two deployment situation on the port level based on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; of the port. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;normal&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; means that the port is
requested to be backed by a normal OVS with directionless resource accounting.
While the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; means the port is requested to be backed by
a hardware-offloaded OVS (or non OVS backend, like SRIOV) with a direction
aware resource inventory.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;No Placement DB schema changes expected.&lt;/p&gt;
&lt;p&gt;For the Neutron DB changes see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No Nova DB schema changes are expected.&lt;/p&gt;
&lt;p&gt;Some Nova o.v.o changes are expected.&lt;/p&gt;
&lt;p&gt;The RequestSpec object already stores a list of RequestGroups as it needs to
support multiple ports and cyborgs devices per Instance already.&lt;/p&gt;
&lt;p&gt;The RequestGroup object does not assume anything about the format of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt; field. However the parts of nova that drives the PCI claim
based on the already allocated bandwidth assumes that the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest.requester_id&lt;/span&gt;&lt;/code&gt; is the same &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;port_id&lt;/span&gt;&lt;/code&gt; as the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup.requester_id&lt;/span&gt;&lt;/code&gt;. To facilitate distinction between different
groups requested by the same port this assumption needs to be removed. This
needs a new field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_id&lt;/span&gt;&lt;/code&gt; in the RequestGroup object that stores the
group id from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requested_resources&lt;/span&gt;&lt;/code&gt; while we keep the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requester_id&lt;/span&gt;&lt;/code&gt;
to be the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;port_id&lt;/span&gt;&lt;/code&gt; as today. The PCI request update logic needs to be
changed to use the group with the bandwidth resource to drive the PCI claim.
This creates an unfortunate dependency between the Nova code and the content
of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt;. We can remove this dependency one we start
modeling PCI devices in Placement.&lt;/p&gt;
&lt;p&gt;The RequestLevelParams object also needs to be extended to store a list of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;same_subtree&lt;/span&gt;&lt;/code&gt; requests coming from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;same_subtree&lt;/span&gt;&lt;/code&gt; field of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;See the changes in the handling of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation&lt;/span&gt;&lt;/code&gt; key in the port’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile&lt;/span&gt;&lt;/code&gt; how this might change in the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Neutron related resource provider model in Placement needs to be extended
with a new inventory of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_EGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt;, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NET_PACKET_RATE_IGR_KILOPACKET_PER_SEC&lt;/span&gt;&lt;/code&gt; resources on the OVS agent resource
providers if such resource inventory is configured in the related agent
configuration by the administrator. Also the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_VNIC_TYPE_&lt;/span&gt;&lt;/code&gt; that today
applied only to the bridge and device RPs needs to be reported on the OVS Agent
RP to facilitate proper scheduling. Note that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PHYSNET_&lt;/span&gt;&lt;/code&gt; traits are
not needed for the packet rate scheduling as this resource is not split
between the available physnets.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;For the Neutron REST API changes see the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This feature does not change the Nova API, only adapts Nova to be able to
consume the new Neutron API extension. A Nova microversion alone could not
signal the availability of the feature to the end user as with Wallaby Neutron
and Xena Nova, even with latest Nova microversion, this feature will not be
available. Therefore now microversion bump will be added. What we suggest
instead is that the end users decide on feature availability based on what QoS
policies the admin created for them. If QoS policies with the new minimum
guaranteed QoS policy rule is available to the end users then they can be sure
that the feature is available. See the &lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2021-05-21.log.html#t2021-05-21T10:51:46"&gt;IRC log&lt;/a&gt; for further discussion.&lt;/p&gt;
&lt;p&gt;If, due to scoping, support for some of the lifecycle operations is not
implemented in the current release cycle then those operations will be rejected
with HTTP 400.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be extra calls to the Neutron &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/extensions&lt;/span&gt;&lt;/code&gt; API during the
server lifecycle operations to detect which format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt;
is used by Neutron and what format the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;binding:profile.allocation&lt;/span&gt;&lt;/code&gt; is
expected by Neutron. This is temporary to support an upgrade scenario where
Nova is already upgraded to Xena but Neutron isn’t. In Y release we can
remove the extra call and assume that Neutron always returns the new format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;No new configuration option is proposed to Nova but to use this feature Neutron
needs to be properly configured. See &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt; for details.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;OpenStack needs to support deployments where the major version of Neutron and
Nova are different. This means that changes for this feature needs to be
written to support both cases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Wallaby Neutron - Xena Nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Xena Neutron - Wallaby Nova&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neutron will introduce a new API extension that will change the structure and
the semantic of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field of the port. Nova needs to
check the existence of the new API extension and parse the field accordingly.&lt;/p&gt;
&lt;p&gt;Neutron needs to make this extension optional with a configuration flag. So
that even if Neutron is upgraded to Xena, the extension and the new API
behavior are not visible so that a Wallaby Nova can still interact with
Neutron successfully.&lt;/p&gt;
&lt;p&gt;In the other hand Xena Nova needs to understand both the old Neutron API if
Neutron is still on Wallaby level, and the new API if Neutron is also upgraded
to Xena.&lt;/p&gt;
&lt;p&gt;After Nova gained full support for the new Neutron API extension, potentially
after Xena, the Neutron API extension can be made mandatory in Neutron. Then
the support for the old format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field can be dropped
from Nova.&lt;/p&gt;
&lt;p&gt;As the changes impacting the nova-compute service a new service version
will be introduced. Nova will reject any lifecycle operation
(server created, delete, migration, resize, evacuate, live-migrate, unshelve
after shelve-offload, interface attach and detach) with HTTP 400 if the new
Neutron API extension is enabled but there are compute services in the
deployment with old service version not supporting the new extension.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Reject all lifecycle operations with HTTP 400 if the Neutron API extension
changing the structure of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field is enabled.
As we add support for each operation the rejection is removed from the given
operation. This way whenever we hit feature freeze we will have a consistent
system that rejects what is not supported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Propose the new resource classes to Placement’s os-resource-classes library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; parsing logic to support the new format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the new parsing logic if the new Neutron API extension is enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each lifecycle operation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Remove assumption from the code that a single port only request a single
request group. If this requires a nova-compute change then bump the service
version and add a check to the API side to reject the operation if there
are old computes in the cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the operation by removing the automatic rejection and keeping only
the service version check.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt the implementation of the nova-manage placement heal_allocation CLI to
the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new Neutron API extension for the port’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; as defined
in the &lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Integration testing can be done in the upstream CI system with the standard
OVS backend through tempest. The hardware-offloaded OVS case cannot be tested
in upstream CI.&lt;/p&gt;
&lt;p&gt;Top of the automatically assumed unit test coverage an extensive set of
functional test will be added to cover the relevant lifecycle operations with
ports having either just minimum packet rate QoS policy rules or both minimum
bandwidth and minimum packet rate QoS rules.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-guide/compute/port_with_resource_request.html"&gt;API guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/ports-with-resource-requests.html"&gt;Admin guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document Nova’s expectation on the format of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_request&lt;/span&gt;&lt;/code&gt; field
of the Neutron port in the developer documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/neutron-specs/+/785236"&gt;Neutron specification&lt;/a&gt; complementing this spec about the neutron details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron RFE for &lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1912460"&gt;packet rate limit policy rule&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 21 May 2021 00:00:00 </pubDate></item><item><title>Rework security group for server details</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/rework-security-group-retrieving.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/rework-security-group-retrieving"&gt;https://blueprints.launchpad.net/nova/+spec/rework-security-group-retrieving&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Generating nova server details could be significantly slowed down if neutron
is used. The cause could be that retrieving security group id/name
requires extra calls to neutron API and number of calls are linear to number
of ports associated with instances divided by 100.&lt;/p&gt;
&lt;p&gt;By removing calling to neutron API, it shows a 30% improvement for server
details. Nova already has an &lt;cite&gt;info_cache&lt;/cite&gt; which saves port name, so we can
take advantage of this and saves security group name as well. By doing this,
we should be able to boost API performance.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Speed up listing of server details and improving API responsiveness.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new mircoversion and allow user to retrieve server detail list without
security group. User will still be able to query security group info through
neutron API, for example
&lt;cite&gt;openstack port list –server ${VM_UUID} -c security_group_ids&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Cache security group names in &lt;cite&gt;info_cache&lt;/cite&gt; for each bounded port, so when
directly retrieving security group from database without calling neutron API.
This will hopefully speed up server detail query given that enough number of
&lt;cite&gt;info_cache&lt;/cite&gt; is populated with security group names. Also note that, update
bounded port will also cause neutron server to callback nova-api and there
update &lt;cite&gt;info_cache&lt;/cite&gt; items.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;&lt;cite&gt;info_cache&lt;/cite&gt; object will have a new property named &lt;cite&gt;security_group&lt;/cite&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a microversion to remove security groups from related APIS when using
neutron network plugin. In the meantime, also remove proxy APIs to query
security groups, user should be able to use neutron API instead.&lt;/p&gt;
&lt;p&gt;Remove security groups from following APIs&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/details&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_uuid}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_uuid}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt; &lt;span class="pre"&gt;where&lt;/span&gt; &lt;span class="pre"&gt;action&lt;/span&gt; &lt;span class="pre"&gt;is&lt;/span&gt; &lt;span class="pre"&gt;rebuild&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following APIs will be deprecated,&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/os-security-groups&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It will still be possible to specify a security group when creating an
instance. This behavior is not modified.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;With the new microversion, user will have to query neutorn API for
security groups&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Querying server details will be accelerated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;nova APIs layer will take care of cache miss and will still query neutron for
security group.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ushen&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Ghanshyam&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Balazs Gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API change to remove the security groups info for new microversion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache security group name in &lt;cite&gt;info_cache&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit and Functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;python-novaclient and osc change&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;add new microversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Adding API functional sample and unit tests to verify security
group is properly returned.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Add a documentation and explain the new microversion as well as server
details may return stale data when quering.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Discussion on IRC about the need for a new API microversion:
&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-xena-ptg"&gt;https://etherpad.opendev.org/p/nova-xena-ptg&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;/section&gt;
</description><pubDate>Sun, 16 May 2021 00:00:00 </pubDate></item><item><title>rootwrap daemon mode</title><link>https://specs.openstack.org/openstack/nova-specs/specs/liberty/implemented/nova-rootwrap-daemon-mode.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-rootwrap-daemon-mode"&gt;https://blueprints.launchpad.net/nova/+spec/nova-rootwrap-daemon-mode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova is one of projects that heavily depends on executing actions on compute
and network nodes that require root priviledges on Linux system. Currently this
is achieved with oslo.rootwrap that has to be run with sudo. Both sudo and
rootwrap produce significant performance overhead. This blueprint is one of the
series of blueprints that would cover mitigating rootwrap part of the overhead
using new mode of operations for rootwrap - daemon mode. Neutron has already
adopted this approach.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As you can see in &lt;a class="footnote-reference brackets" href="#ne-ml" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; rootwrap presents big performance overhead for
Neutron. Impact on Nova is not as signigicant since most of the work is done
with libvirt’s API but it is still there.
Details of the overhead are covered in &lt;a class="footnote-reference brackets" href="#rw-bp" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;This will eliminate bottleneck in nova-network, nova-compute at boot large of
number of nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="project-priority"&gt;
&lt;h3&gt;Project Priority&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This blueprint proposes adopting functionality in oslo.rootwrap that would
allow to run rootwrap daemon. The daemon will work just as a usual rootwrap but
will accept commands to be run over authenticated UNIX domain socket instead of
command line and will run continuously in background.&lt;/p&gt;
&lt;p&gt;Note that this is not usual RPC over some message queue. It uses UNIX socket,
so no remote connections are available. It also uses digest authentication with
key shared over stdout (pipe) with parent process, so no other processes will
have access to the daemon. Further details of rootwrap daemon are covered in
&lt;a class="footnote-reference brackets" href="#rw-bp" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_rootwrap_daemon&lt;/span&gt;&lt;/code&gt; configuration option should be added that will make
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;utils.execute&lt;/span&gt;&lt;/code&gt; use daemon instead of usual rootwrap.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Alternative approaches have been discussed for Neutron in &lt;a class="footnote-reference brackets" href="#ne-eth" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This change requires additional endpoint to be available to run as root -
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-rootwrap-daemon&lt;/span&gt;&lt;/code&gt;. It should be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudoers&lt;/span&gt;&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;All security issues with using client+daemon instead of plain rootwrap are
covered in &lt;a class="footnote-reference brackets" href="#rw-bp" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This change introduces performance boost for disk and network operations that
are required to be run with root priviledges in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-network&lt;/span&gt;&lt;/code&gt;. Current state of rootwrap daemon shows over 10x speedup
comparing to usual &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudo&lt;/span&gt; &lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt; call. Total speedup for Nova will be less
impressive but should be noticeable.&lt;/p&gt;
&lt;p&gt;Looking at numbers from check-tempest-dsvm-full CI job (&lt;a class="footnote-reference brackets" href="#nova-perf" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;) with
the rootwrap daemon mode on and off, here’s what we see:&lt;/p&gt;
&lt;p&gt;Daemon Off - Average 0.08981064764 seconds
Daemon On  - Average 0.02984345922 seconds&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;This change introduces new config variable &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_rootwrap_daemon&lt;/span&gt;&lt;/code&gt; that
switches on new behavior. Note that by default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_rootwrap_daemon&lt;/span&gt;&lt;/code&gt; will be
turned off so to get the speedup one will have to turn it on. With it turned on
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-rootwrap-daemon&lt;/span&gt;&lt;/code&gt; is used to run commands that require root priviledges.&lt;/p&gt;
&lt;p&gt;This change also introduces new binary &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-rootwrap-daemon&lt;/span&gt;&lt;/code&gt; that should
be deployed beside &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-rootwrap&lt;/span&gt;&lt;/code&gt; and added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudoers&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Davanum Srinivas &amp;lt;&lt;a class="reference external" href="mailto:davanum%40gmail.com"&gt;davanum&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;The only work item here is to implement new config variable and run rootwrap in
daemon mode with it.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;rootwrap-daemon-mode blueprint in oslo.rootwrap &lt;a class="footnote-reference brackets" href="#rw-bp" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This change doesn’t change APIs so it doesn’t require additional integration
tests. If tempest is happy with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_rootwrap_daemon&lt;/span&gt;&lt;/code&gt; turned on, the feature
works. We can turn this flag on for some of the jobs say the nova-network
job.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="rw-bp" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;4&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;oslo.rootwrap blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-rootwrap-daemon-mode"&gt;https://blueprints.launchpad.net/nova/+spec/nova-rootwrap-daemon-mode&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="ne-ml" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Original mailing list thread:
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-March/029017.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-March/029017.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="ne-eth" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Original problem statement summarized here:
&lt;a class="reference external" href="https://etherpad.openstack.org/p/neutron-agent-exec-performance"&gt;https://etherpad.openstack.org/p/neutron-agent-exec-performance&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="nova-perf" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Nova check-tempest-dsvm-full comparison:
&lt;a class="reference external" href="https://docs.google.com/spreadsheets/d/1sxhan2fRg6eshY4559O8z1g8sFPRXma00xz53nZ6sAI/edit#gid=870990378"&gt;https://docs.google.com/spreadsheets/d/1sxhan2fRg6eshY4559O8z1g8sFPRXma00xz53nZ6sAI/edit#gid=870990378&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Tue, 04 May 2021 00:00:00 </pubDate></item><item><title>Unified Limits Integration in Nova</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/unified-limits-nova.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unified-limits-nova"&gt;https://blueprints.launchpad.net/nova/+spec/unified-limits-nova&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec is about adopting Keystone’s unified-limits.
Includes using oslo.limit to enforce the Nova related limits set in Keystone.&lt;/p&gt;
&lt;p&gt;This spec proposes having unified limits in parallel with the existing
quota system for at least one cycle, to allow for operators to transition
from setting quotas via Nova to setting limits relating to the Nova API
endpoint via Keystone.&lt;/p&gt;
&lt;p&gt;All per user quota support is dropped, in favor of hierarchical
enforcement that will be supported by unified limits.&lt;/p&gt;
&lt;p&gt;Only server count limits and limits on Resource Class resources requested in
the flavor will be supported with unified limits. All other existing quotas
will no longer support per project or per user limits.&lt;/p&gt;
&lt;p&gt;Given this placement focused approach, we will depend on the work done here:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;While much work has been done to simplify how quotas are implemented in
Nova, there are still some major usability issues for operators with
the current system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We don’t have consistent support for limit/quota hierarchy across OpenStack&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requiring operators to set limits individually in each service
(i.e. Cinder, Nova, Neutron, etc)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova’s existing quotas don’t work well with Ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No support for custom Resource Class quotas (includes “per flavor” quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confusion when API defined quota limits override any changes made to the
configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some Nova quotas are unrelated to resource consumption, causing confusion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transitioning to use Keystone’s unified limits, via oslo.limit, will help fix
these issues.&lt;/p&gt;
&lt;p&gt;For more details on unified limits in keystone see:
&lt;a class="reference external" href="https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html"&gt;https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The key use cases driving this work are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API User tries to understand why they got an Over Quota error&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator migrates to unified limits from existing limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator sets a default limit for a given endpoint via Keystone. Note there
can be different limits for each Region, even with a shared Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator sets specific limits for a given project via Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator defines limits of a set of projects via non-flat enforcement
i.e. the feature formally known as hierarchical quotas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will focus on adding unified limits relating to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;total number of servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amounts of each Resource Class requested in the flavor&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note, this includes things like DISK_GB which is not supported today,
along with things like custom resource class resources that are requested
in extra specs (e.g. Ironic flavors).&lt;/p&gt;
&lt;p&gt;We will now look at all quotas exposed via the API and what they map to
when using unifed limits:
&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota"&gt;https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The follow existing quota types move to unified limits, allowing for
per endpoint defaults and per project overrides (and hierarchical limits)
via the unified limits system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cores&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource:VCPU&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_count&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ram&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource:MEMORY_MB&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following existing quota becomes defined only by a configuration
option, and we no longer support and per project or user overrides
via the API, we just report the existing limit as defined in the
configuration:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_pairs&lt;/span&gt;&lt;/code&gt; (counted per user)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt; (counted per project)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt; (counted per server group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;metadata_items&lt;/span&gt;&lt;/code&gt; (counted per server)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above are purely protecting database bloat (i.e to stop a denial
of service attack that fills up the database). They are similar to the
hardcoded limit of the number of tags you can attach to a server.&lt;/p&gt;
&lt;p&gt;While deprecated in the API, we will also treat these quotas in the
same way as the quotas above, i.e. they will now be set via
confirguration with no per project overrides possible:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are several parts to this spec:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enforce Unified Limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No per-user limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No uncountable limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate Nova’s Quota APIs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator tooling to assist with the migration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="enforcing-unified-limits"&gt;
&lt;h3&gt;Enforcing Unified Limits&lt;/h3&gt;
&lt;p&gt;We will support the following limits:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_count&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource:&amp;lt;RESOURCE_CLASS&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the resource class usage will be counted using placement, but
server count will make use of instance mappings. This only works if the
queued for delete data migration has been completed. Due to no user
based quotas, we don’t need the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; migration. If the operators
tries to use unified limits before completing the migration, the code
will block all new usage until the migration is completed. It is
expected a blocking migration will be added before we turn on unified
limits by default. For more details on the this data migration see
this point in the existing quota code:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053"&gt;https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To allow the new system to co-exist with the older quota system, we make
use of the existing quota driver sytem. The default will be unchanged,
but operators can opt-into the new system in the following way:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]driver=nova.quota.UnifiedLimitsDriver&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For further details on the transition, please see the update section of this
specification. Note the new unified limits code will have a hard dependency
on counting usage via placement; as such it will ignore the value of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.quota.count_usage_from_placement&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the existing quotas, &lt;cite&gt;instances&lt;/cite&gt; becomes &lt;cite&gt;server_count&lt;/cite&gt;,
&lt;cite&gt;cores&lt;/cite&gt; becomes &lt;cite&gt;resource:VCPU&lt;/cite&gt; and &lt;cite&gt;ram&lt;/cite&gt; becomes &lt;cite&gt;resource:MEMORY_MB&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;This work will re-use a lot of the new logic to query placement for resource
usage, and use the instance mapping table to count servers added in this spec:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To find out what resources a server will claim, we reuse this
code to extract the resources from any given flavor:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387"&gt;https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For server build, we use the above function to get the Resource Class
resource amounts for the requested flavor. This will then be checked using
olso.limit, which ensures the additional usage will not push the associated
project over any of its limits. The oslo.limit library is responsible for
counting all the current resource usage using a callback we provide that makes
use of placement to count the current resource usage.&lt;/p&gt;
&lt;p&gt;Once resources are claimed in placement, we optionally recheck the limits
to see if we were racing with other server builds to consume the last bits
of available quota. The only change is using oslo.limit to do the recheck.
That is, we will still respect the config: &lt;cite&gt;quota.recheck_quota&lt;/cite&gt;
Note: we do the first check of limits in nova-api, and the recheck in
nova-conductor after resource allocation in placement succeeds.&lt;/p&gt;
&lt;p&gt;It is a similar story with resize. Except in this case, we check that we can
claim resources for both the new flavor and old flavor at the same time.
Note that this is quite different to the current quota system, even when
counting usage via placement.&lt;/p&gt;
&lt;p&gt;For further details on the semantic changes relating to counting with
placement see:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note baremetal instances no longer claim any VCPU or MEMORY_MB resources.
With this method, baremetal instances can be limited using custom
resource class resources they request in the flavor.&lt;/p&gt;
&lt;p&gt;Should we choose to allow additional custom inventory entries
from hypervisor based compute nodes, such as &lt;cite&gt;{‘CUSTOM_GPU_V100’:1}&lt;/cite&gt;
we will be also be able to apply quotas on these resources.&lt;/p&gt;
&lt;p&gt;The oslo.limits library will likely add additional configuration options.
In particular, operators will need to specify the Nova API’s endpoint uuid
to oslo.limit, so it knows what unified limits apply to each particular
Nova API service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="no-per-user-limits"&gt;
&lt;h3&gt;No per user limits&lt;/h3&gt;
&lt;p&gt;Nova currently supports “per user” limits. They will no longer be supported
when:  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are no plans for migration tools, however it is expected that users
that need a similar model can test out using the unified limits support for
hierarchical limits, and report back on what could help others migrate.&lt;/p&gt;
&lt;p&gt;Note: Keypairs will still have a max limit enforced, and that max limit
will still be enforced per user. However, there will now only be a single
global configuration value in Nova to set the max number of keypairs
each user is allowed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="no-uncountable-limits"&gt;
&lt;h3&gt;No uncountable limits&lt;/h3&gt;
&lt;p&gt;As stated above, the focus for unified limits is the instance count and
resource class allocations in placement. No other limits will be moved to
unified limits, as agreed with operators in the Train Forum session.&lt;/p&gt;
&lt;p&gt;There are limits that are specific to nova-network. These are all ready
deprecated. There are no plans to support these with unified limits turned on:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixed_ips&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;floating_ip&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security_group_rules&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;networks&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The remaining limits are all mainly used to protect the database from rogue
users using up all available space in the database and/or missuse the API as
some sort of storage system. As such, it is not expected that operators need
per project overrides for any of these limits. As such, we propose to drop
support for changing the limits via the API, and instead only allow changing
of the limits via a single configuration option that applies to all
projects in the system.&lt;/p&gt;
&lt;p&gt;The following limits will be changed to only be set via a single configuration
option that applies equally to all projects:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;metadata&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_pairs&lt;/span&gt;&lt;/code&gt; (counted per user)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt; (counted per project)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt; (counted per server group)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the server_group_members are currently counted per user, but this
is frankly very confusing, so above we propose the simpler limit servers
in the server group. This seems consistent with removing per user limits for
all other project owned resources.&lt;/p&gt;
&lt;p&gt;Using a global configuration option only means:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;no per project overrides&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;no per user overrides&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;no changing of limits via the API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are limits on the amount of data that can be stored in various
Nova databases. There is no way to display a project’s usage of these limits,
which further demonstrates how these are different to the resource limits
unified limits has been designed for.&lt;/p&gt;
&lt;p&gt;Currently we honor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; for all of these quotas. This adds
significant code complexity, however most users never hit these limits and
they are all very soft limits. As such, when we transition to a single global
configuration value for all of these, we also will stop doing any rechecks.&lt;/p&gt;
&lt;p&gt;In summary the impact on the configuration options is:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; will have an updated description, noting what
functionality is lost when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.floating_ips&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.fixed_ips&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.security_groups&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security_group_rules&lt;/span&gt;&lt;/code&gt;: remain deprecated, and will be ignored when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.metadata_items&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_files&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_file_path_length&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.server_groups&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.server_groups_members&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.key_pairs&lt;/span&gt;&lt;/code&gt;:  these will all be
kept, but the description will be updated to note if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; all updates via the API are ignored.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="deprecate-nova-s-quota-apis"&gt;
&lt;h3&gt;Deprecate Nova’s Quota APIs&lt;/h3&gt;
&lt;p&gt;To query and set limits, Keystones APIs should be used. To query a user’s
usage, the Placement API should be used, assuming placement is happy
changing the default policy to allow users to query their usage.&lt;/p&gt;
&lt;p&gt;The one exception is server count can’t currently be checked via
Placement. When placement implements consumer records,
or similar, then all usage could be queried via Placement. To avoid
using a proxy API, users can do a server list API and count the number
of servers returned.&lt;/p&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; a best effort will be made to
keep the older micro-versions working by proxing API calls to Keystone and
Placement as needed. No quota related DB tables will be accessed when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This includes the follow API resources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;/limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/os-quota-sets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/os-quota-class-sets&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing tooling to set quotas should continue to operate, as long as it only
changes quotas relating to instances, cores and ram. Requests to change any
other quotas will be silently ignored. As one example, this should allow
Horizon to function as normal during the transition.&lt;/p&gt;
&lt;p&gt;When you list limits for quotas that are not supported in the new system, they
will instead show the configuration based limit that replaces the DB and API
based limits, e.g. for keypairs you always see the config based value, no
update via the API will ever be reflected back when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are some trade-offs with this approach:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Proxy APIs suck, but horizon must keep working as such all current operator
tooling around these existing APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We don’t need a micro version to enable/disable this proxy
of the quota APIs, as it doesn’t really change the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a future release when unifed limits becomes the default,
we should deprecate the APIs
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-quota-sets&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-quota-class-sets&lt;/span&gt;&lt;/code&gt; and tell users to talk to
the Keystone API instead. API based discovery of when Nova is enforcing
the limits set in Keystone is left for a future spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is expected the above API deprecation will follow the pattern used
by nova-network proxy APIs, i.e. the APIs return 404 in new microversions
but continue to work in older microversions. Its possible in the more
distant future the APIs could be removed by returning 410 error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rejecting updates to quotas that we were previously able to set would be a
breaking change in behaviour, and require a microversion. Adding a new API
microversion that returns BadRequest for unsupported quotas would be a nice
addition if we were not planning on deprecating the API in favor of calling
Keystone instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideally we would also deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; in favor of a cross project
agreed direction that is aware of both flat and hierarchical limit
enforcement. Howerver we do not yet have consenus on what direction
we take. For this spec, we leave &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; in its current form, even
though it does not report on all the types of resource usage we now
support have limits on, and even though it lists limits that can
now only be changed via the configuration file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When hierarchical limits are added, the per project usage information
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; does not mention anything about parent limits.
As such quota APIs may claim resources are available, but you will be
unable to build any new resources.
It is not clear what action the user can make to be able to build those new
resources. Operators can avoid this confusion by not over allocating quota.
We could extext the API to include a boolean to say if the limit has been
exceeded in the parent project, and as such the user is unable to consume
more resources even though their own usage is not over their own limits.
We could consider extending the API to include the usage of the full tree&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="migration-to-unified-limits"&gt;
&lt;h3&gt;Migration to Unified Limits&lt;/h3&gt;
&lt;p&gt;The migration of all users to unified limits is happening in three phases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;enable unified limits as an option, with migration path from existing quotas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;make unified limits the default, deprecate existing quota system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove existing quota system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To help with the transition we need operator tooling to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Set registered limits in Keystone for each Nova endpoint in Keystone,
based on current limits in DB and/or configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy per-project quotas set in Nova into Keystone unified-limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator confirms unified limits works for them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drop all quota info from the DB to signal operator has completed transition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade status check to check there is no data left in quota DB tables&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note the setting of project limits and registered limits in keystone will
happen via files that are generated and passed to keystone-manage. This
allows fast-forward upgrades where no API are available during the migration
of limits from Nova to Keystone.&lt;/p&gt;
&lt;p&gt;There will be a new tool to setup the registered limits in keystone. It will
read from the Nova DB and configuration and generate a file. That file can be
by used with keystone-manage to register the current endpoint defaults in
keystone.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;generate_registered_limits&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following tool will generate the unified limits overrides (if any)
that needs to be added into Keystone for each project. Again this too
produces a file that is handed to keystone-manage which will update keystone:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;generate_project_limits&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once the operator sets &lt;cite&gt;quota.enforce_unified_limits = True&lt;/cite&gt;, the Nova DB is
ignored, and limits are accessed from Keystone only.&lt;/p&gt;
&lt;p&gt;To complete the migration, there is an operation to remove all the
DB entries relating to the quota overrides. The tool only works when
&lt;cite&gt;quota.enforce_unified_limits = True&lt;/cite&gt;. It also removes all any per user limits
associated with each project.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;remove_db_quota_entries&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note the last two tools allow operators to iterate per project, to limit the
load on the running system. If these tools are used on a running system, it is
recommended that operators don’t change quotas via the API during the
transition.&lt;/p&gt;
&lt;p&gt;The nova status command will warn users that have failed to remove all the
quota information from the DB. This will become an error in the release when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt;&lt;/code&gt; defaults to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is worth noting that the Nova database may contain entries for projects
that have been deleted in keystone. As such, it is advisable to get a list
of active projects from keystone, and only generate_project_limits for those
particular projects.&lt;/p&gt;
&lt;p&gt;This transition leaves several configuration options redundant, in particular
the following will all be deprecated once unified limits is on by default:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.instances&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.cores&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.ram&lt;/span&gt;&lt;/code&gt;: deprecate all these as
the limit now comes from keystone for unified limits, which will default to
unlimited if there is no limit in keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.driver&lt;/span&gt;&lt;/code&gt; is ignored and hard coded to the no-op driver when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; will be kept, and will be used in the same
way with unified limits to avoid races when multiple instances are built at
the same time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Ideally we would not add any more proxy APIs, however, operators pushed back
at the Train Forum session, requesting that their tooling continue to work
across the transition. No operators reported using limits other than the
instances, cores and ram limits.&lt;/p&gt;
&lt;p&gt;We could implement hierarchical quotas in isolation, and not adopt unified
limits.&lt;/p&gt;
&lt;p&gt;We could limit the types of resources we limit, but it will be hard to
transition to supporting different kinds of resource limits in a clear
and interoperable way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See upgrades, no changes in Victora due to having old and new quota systems
side by side. Once we remove the old quota system, we could drop all the
quota related DB tables.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; Nova will proxy the requests
to Keystone’s unified limits API, where possible. The aim will be to keep
horizon functioning correctly during the transition.&lt;/p&gt;
&lt;p&gt;Once using unified limits, operators should move to using Keystone’s
unified limit APIs to set and query limits. Usage information should be
queried via Placement and the Servers API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The removal of quota rechecks for some limits slightly reduces the protection
provided, but really it encourages the proper implementation of API
rate limiting as replacement protection.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Quota errors should appear the same before and after this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;It is possible to have more complicated quota counts with hierarchical
quotas, but the implementation of that is delegated to oslo.limit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;There are several tools to help ease the transition to unified limits noted
above. Although it is expected that use of the feature will help inform the
end direction.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;There will now be two limit system to maintain for a few cycles during the
transition. But this avoids the long term need to maintain complicated
hierarchical limit code, which still getting the advantages, such as being able
to tidy up API policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;To get the best experience, operators need to start using the unified limits
API via Keystone. User should start querying usage from Placement.&lt;/p&gt;
&lt;p&gt;The transition between the existing quota system and unified limits is
detailed in the proposed solution section.&lt;/p&gt;
&lt;p&gt;It is expected that oslo.limit will limit versions of Keystone that can be
used to Queens and newer, which is not expected to affect most users.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(TBC)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add calls to oslo_limits, guarded by config to enable it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move quota APIs to proxy to Keystone when unified limit quotas enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tools to migrate default and tenant limits from Nova into Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade checks to ensure above tooling is used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keystone manage commands to add limits when keystone API not available&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Grenade test that runs the migration of quota settings (after adding some
quotas).&lt;/p&gt;
&lt;p&gt;Functional tests to ensure quotas are enforced based on unified limits
correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Building on the work to document quota usage from placement, we should
describe how the new system operates. The admin guide needs to detail
how to smoothly migrate to unified limits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victora&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 04 May 2021 00:00:00 </pubDate></item><item><title>Allow migrating PMEM’s data</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/allow-migrate-pmem-data.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/allow-migrate-pmem-data"&gt;https://blueprints.launchpad.net/nova/+spec/allow-migrate-pmem-data&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes an method for migrating PMEM Namespace’s data of instance
when cold migrating or resizing instance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, cold migrate or resize instance will always select a new pmem
namespace on the destination host. But the data of the instance in the PMEM
device will be lost. To ensure the integrity of instance data， we would like
to migrate PMEM’s data of the instance when migrate or resize an instance.&lt;/p&gt;
&lt;p&gt;PMEM devices can be used as a large pool of low latency high bandwidth memory
where they could store data for computation. This can improve the performance
of the instance.&lt;/p&gt;
&lt;p&gt;Since copying pmem data will take a lot more time and network bandwidth, a new
“copy_pmem_devices” argument is added to decide whether to copy pmem data.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an user, I would like to migrate the PMEM namespace’s data if the instance
migrate or resize to another host to ensure data integrity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion migrate / resize API, introducing “copy_pmem_devices”
field.&lt;/p&gt;
&lt;p&gt;When migrating or resizing intance, we can get the old PMEM device and the new
PMEM device from &lt;cite&gt;instance.migration_context&lt;/cite&gt;. So we can copy the data from old
PMEM device to new PMEM device.&lt;/p&gt;
&lt;p&gt;Given or Assuming, the instance use /dev/dax0.0 PMEM Namespace on the source
host, and we want to migrate or resize it to other host, and migrating or
resizing the instance, will use the /dev/dax0.1 PMEM namepsace on the target
host.
Then nova will migrate the PMEM namepace’s data of the instance from
/dev/dax0.0 to /dev/dax0.1 using the daxio utility over an ssh tunnel.&lt;/p&gt;
&lt;section id="workflow"&gt;
&lt;h3&gt;Workflow&lt;/h3&gt;
&lt;p&gt;cold migrating or resizing instance workflow as following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;prep_resize validates that there is a pmem device free and claims it as
part of the move_claim process.The claimed device is stored in the
instance.migration_context which can be retrieved later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The resize_instance operation is on source_compute, free the network volume
etc. resources. We can get the source compute, dest compute from migration,
and get the new PMEM device, old PMEM device from
instance.migration_context. Copy the PMEM data from old PMEM device to new
PMEM device at migtate_disk_and_power_off. If the copy operation is failed,
cleanup the PMEM data on dest_compute, and make the instance ACTIVE again
on the source compute. Copy the PMEM data can use “daxio” and “ssh”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The finish_resize operation is on dest_compute, launching a new instance
with resources in step1. If launching new instance failed, will terminate
the operation, cleanup the PMEM data on dest_compute, and make the instance
ACTIVE again on the source compute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The confirm_migration will cleanup PMEM data on source compute, alternitivly
revert_resize will cleanup PMEM data on dest compute and  make the instance
ACTIVE again on the source compute.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a new microversion migrate / resize API with “copy_pmem_devices” field.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action
{&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;“resize”&lt;span class="classifier"&gt;{&lt;/span&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;“flavorRef” : “2”,
“OS-DCF:diskConfig”: “AUTO”,
“copy_pmem_devices”: “true”&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;“migrate”: {&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;“host”: “host1”,
“copy_pmem_devices”: “true”&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The value of “copy_pmem_devices” default “false”, dosen’t copy pmem data.
“true”, the data in virtual persistent memory is copied.&lt;/p&gt;
&lt;p&gt;If the copy_pmem_devices=true and the old microverion return a 400. Cross cell
resize/cold migrate, will return 400.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The pmem data will be transfered over ssh using the daxio utility to read and
write the data, e.g. daxio -ouput /dev/dax0.0 | ssh &amp;lt;dest_compute_ip&amp;gt; “daxio
-input /dev/dax0.1” This will reuse the exising ssh_execute function used to
implement the ssh remote fs driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;PMEM data will not be copied if performing a cross cell resize/migration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;A cold migrate / resize operation will take a lot more time and network
bandwidth than before as it needs to copy the content of the pmem between
compute hosts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;This change will impact host the nova-compute service will behave during
migration / resize so the compute service version needs to be bumped. Also
resize and migration with pmem copy will only work with new enough compute
services so a compute service version check should be implemented for these
operations.&lt;/p&gt;
&lt;p&gt;If the copy_pmem_devices=false or the old microverion we proceed with the old
behavior of not copying the data. If the copy_pmem_devices=true and the old
microverion return a 400.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;QIU FOSSEN(&lt;a class="reference external" href="mailto:qiujunting%40inspur.com"&gt;qiujunting&lt;span&gt;@&lt;/span&gt;inspur&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add related unit test for negative scenarios.
Add related functional test (API samples).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the related documents and add some description of this change&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1] &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/virtual-persistent-memory.html"&gt;https://docs.openstack.org/nova/latest/admin/virtual-persistent-memory.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 09 Apr 2021 00:00:00 </pubDate></item><item><title>Allow including &amp;#64; and . (dot) characters in keypair name</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/allow-special-characters-in-keypair-name.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/allow-special-characters-in-keypair-name"&gt;https://blueprints.launchpad.net/nova/+spec/allow-special-characters-in-keypair-name&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Keypair names currently allow only digits, ascii letters, dashs,
underscores and spaces.&lt;/p&gt;
&lt;p&gt;When user tries to insert any other character, he gets the error:
“Keypair name contains unsafe characters”.&lt;/p&gt;
&lt;p&gt;Allowing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@&lt;/span&gt;&lt;/code&gt; (at) and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; (dot) characters in keypair names make it
possible to use the format &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user.name@host.name&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;More context:&lt;/p&gt;
&lt;p&gt;Check is done by
&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/commit/5ea4f712c583c87a24eb6aafb6d3835d534a171c/nova/compute/api.py#L6422"&gt;https://opendev.org/openstack/nova/src/commit/5ea4f712c583c87a24eb6aafb6d3835d534a171c/nova/compute/api.py#L6422&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It was introduced by
&lt;a class="reference external" href="https://opendev.org/openstack/nova/commit/c8b0a9a3be7ca276d91d470a629fdd0209812993"&gt;https://opendev.org/openstack/nova/commit/c8b0a9a3be7ca276d91d470a629fdd0209812993&lt;/a&gt;,
to resolve &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/937408"&gt;https://bugs.launchpad.net/nova/+bug/937408&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Only modified once since to include space in
&lt;a class="reference external" href="https://opendev.org/openstack/nova/commit/ec0a65d81fd11d26be77b45827a4dd7c77711675"&gt;https://opendev.org/openstack/nova/commit/ec0a65d81fd11d26be77b45827a4dd7c77711675&lt;/a&gt;&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Some end users have the habit of using the format &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user.name@host.name&lt;/span&gt;&lt;/code&gt; in
their keypair name, probably because it is the default comment
generated by ssh-keygen.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Modify the list of safe characters to add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@&lt;/span&gt;&lt;/code&gt; (at) and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; (dot).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Existing microversion should keep these characters forbidden.
A new microversion will allow these characters.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nautik&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Liaison Needed&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Adding unit tests should be enough to test these special characters.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;API reference documentation should explain what characters are allowed
for keypair names.
See &lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=create-or-import-keypair-detail#create-or-import-keypair"&gt;https://docs.openstack.org/api-ref/compute/?expanded=create-or-import-keypair-detail#create-or-import-keypair&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Discussion on IRC about the need for a new API microversion:
&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2021-03-19.log.html#t2021-03-19T10:02:01"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2021-03-19.log.html#t2021-03-19T10:02:01&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 09 Apr 2021 00:00:00 </pubDate></item><item><title>libvirt supports composing cyborg owned vGPU into domain XML</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/cyborg-vgpu-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cyborg-vgpu-support"&gt;https://blueprints.launchpad.net/nova/+spec/cyborg-vgpu-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to enable vGPU accelerator in nova and cyborg
interaction.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In order to allow operators to use cyborg to manage the lifecycle of vGPU,
cyborg needs to discover the vGPUs, reports them to placement, and instruct
nova to allocate a specific vgpu mdev to the instance. Cyborg managed vGPUs
will not replace nova’s native vGPU capabilities &lt;a class="footnote-reference brackets" href="#id6" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and will provide an
alternative management mechanism in parallel to the existing nova feature.&lt;/p&gt;
&lt;p&gt;In the current cyborg-nova interaction &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, there is still a small gap in
allocating a cyborg owned vGPU to an instance. This spec proposes to support
composing cyborg owned vGPU into domain XML in nova libvirt driver.&lt;/p&gt;
&lt;p&gt;For more information about cyborg side lifecycle management (discover, data
modeling etc.) of vGPU please refer to &lt;a class="footnote-reference brackets" href="#id8" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to use Cyborg to manage the lifecycle of vGPUs.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Define the data model in arq to track a cyborg owned vGPU.&lt;/p&gt;
&lt;p&gt;This data model should provide attach_handle_type to distinguish from a
PCI device accelerator, and attach_handle_uuid as the mdev UUID which is
used to create a mdev device in the /sys/class/mdev_bus/…, as well as
the asked vgpu type of this device. The format will be like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'attach_handle_type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'MDEV'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'attach_handle_uuid'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'91ac1606-427e-44bb-8233-f4ff4bf3d241'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova virt driver merge the mdev info from arq into the XML of an instance.&lt;/p&gt;
&lt;p&gt;This will need to get mdevs form arq list and pass it to generate guest xml
in nova/virt/libvirt/driver.py &lt;a class="footnote-reference brackets" href="#id9" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Please be aware that the following is
just the pseudocode to show the whole function and process.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Get mdevs accelerators from ARQ list.&lt;/span&gt;
&lt;span class="n"&gt;mdev_arq_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arq&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;acc_info&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'attach_handle_type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'MDEV'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;mdevs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mdevs_accel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_guest_xml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;network_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;block_disk_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;block_device_info&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;block_device_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;mdevs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mdevs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mdev_arq_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arq&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;acc_info&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'attach_handle_type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'MDEV'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_guest_add_accel_mdev_devices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mdev_arq_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;_guest_add_accel_mdev_devices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc_info&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Adding mdev accelerators from ARQ list.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;acc_info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_guest_add_mdevs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'attach_handle_uuid'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cyborg creates mdev device in the sys path&lt;/p&gt;
&lt;p&gt;In theory, if nova and cyborg both can support vGPU management, nova or
cyborg should support create mdev in its own respective. Therefore, in the
cyborg lifecycle management of vGPU, cyborg should creates mdev beforehead,
nova virt driver uses it as an existed resousrce.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;spawn instance interaction(arq interaction part):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;nova-conductor requests cyborg to create and bind arq:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;cyborg-api rpc.call the cyborg-agent to create a new mdev&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cyborg-agent sucessfully created mdev and returns result&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cyborg start bind arq&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cyborg arq successfully bound and notify nova that ARQ bindings
are resolved for a given instance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-compute receives bound notification and GET resolved arq&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-compute calls virt driver to spawn an instance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;reboot instance interaction: when nova-compute calls cyborg GET arq
API, cyborg does the db lookup and returns the expected arq.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;host reboot: cyborg-owned vGPU will be missing from the sys path after
host reboot. The cyborg agent should create the mdevs for all bound arqs
on start up. Ideally it would set the binding state to “provisioning” on
start up also. And we would have anohter state “unknown” that cyborg-api
would report if the cyborg agent misses its heart beat.
So on start up, when nova compute tries to get accel_info and reboot all
the instances, it would see 1 of 3 states, “bound” if the cyborg agent
started first and already completed bininding, “unknown” if the cyborg
agent has not heartbeat to the cyborg conductor yet, and “provisioning”
if the agent is in the process of creating the mdev. Cyborg will send the
same binding complete event notification when it change the status form
“provisioning” to “bound” as it does during normal arq binding.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid conflicts when cyborg vGPU management co-exists with nova
vGPU management.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use owner (nova, cyborg) trait in Placement when inventory is reported.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This will need to add a new namespace in os-traits: OWNER_*.
Then nova/cyborg report owner trait OWNER_NOVA/OWNER_CYBORG
as one of the trait when inventory is reported.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the cyborg driver, it will report two traits for vGPU accelerator
using the format below. For more details, pls refer to the driver
spec &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;trait1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OWNER_CYBORG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;trait2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CUSTOM_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VENDOR_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PRODUCT_ID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Virtual_GPU_Type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the nova side, it will need to report a new trait &lt;strong&gt;OWNER_NOVA&lt;/strong&gt;
for vGPU resources during inventory report.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the end user makes a vGPU request, for a nova owned vGPU request,
one can specify &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources##:VGPU=1&lt;/span&gt;&lt;/code&gt; in flavor. For a cyborg owned
vGPU, one need specify in pre-defined device profile, then add it to
flavor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In libvirt driver, use a mdev_tag to identify which vGPU is the current
operation request(eg. spawn, reboot) going to land. If it is cyborg vGPU,
tag will be ‘ACCELERATOR’, otherwise it is ‘COMPUTE’.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This will need to add a new fuction _get_mdev_tag to identify this
according to the given accel_info, and return a tag mdev_tag:’COMPUTE’
or ‘ACCELERATOR’ to indicate this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;_get_mdev_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accel_info&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Identify which vGPU is the current request going to land.&lt;/span&gt;

&lt;span class="sd"&gt;       parameter: accel_info&lt;/span&gt;
&lt;span class="sd"&gt;       return: mdev_tag('COMPUTE' or 'ACCELERATOR')&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;accel_info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# here is just to show the logic specification&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;accel_info&lt;/span&gt; &lt;span class="n"&gt;contains&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;arq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'attach_handle_type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'MDEV'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;arq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'attach_handle_uuid'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
             &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;arq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'attach_handle_info'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'asked_type'&lt;/span&gt;&lt;span class="p"&gt;]}:&lt;/span&gt;
                &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ACCELERATOR'&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'COMPUTE'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;And accordingly, we will also need new change in mdev_tag’s consumer
side, the nova operations side, such as hard_reboot and spawn.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployer should make sure the device in one pci address is not configured in
both Nova and Cyborg. If it is configured in both Cyborg and Nova should be
able to raise this as an conflict exception.
If the deployer configure same device in both Cyborg and Nova, they may report
same data to Placement at the same time, we can raise conflict exception at
Placement side, and return to Cyborg or Nova, and warn the deployer about
the conflict device.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;For those who want to upgrade from nova-owned vGPU to cyborg-owned vGPU,
one can resize directly from a flavor with a nova managed gpu
(resouces:vgpu=1 in the flavor) to a flavor with a cyborg managed vgpu
(accel:device-profile=cyborg-vgpu-device-profile-name).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Wenping Song &amp;lt;&lt;a class="reference external" href="mailto:songwenping%40inspur.com"&gt;songwenping&lt;span&gt;@&lt;/span&gt;inspur&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;yumeng-bao&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Brin Zhang &amp;lt;&lt;a class="reference external" href="mailto:zhangbailin%40inspur.com"&gt;zhangbailin&lt;span&gt;@&lt;/span&gt;inspur&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Schedule vGPU resources by device profile&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create vGPU mdev when spawn guest&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit test and function test to be added&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New unit test should be added&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Document need to be changed to describe this feature&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/ussuri/admin/virtual-gpu.html"&gt;https://docs.openstack.org/nova/ussuri/admin/virtual-gpu.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/nova-cyborg-interaction.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/nova-cyborg-interaction.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/758925/"&gt;https://review.opendev.org/#/c/758925/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/master/nova/virt/libvirt/driver.py#L6139"&gt;https://github.com/openstack/nova/blob/master/nova/virt/libvirt/driver.py#L6139&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id10"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Flavour and Image defined ephemeral storage encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/ephemeral-storage-encryption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a new approach to ephemeral storage encryption in Nova
allowing users to select how their ephemeral storage is encrypted at rest
through the use of flavors with specific extra specs or images with specific
properties. The aim being to bring the ephemeral storage encryption experience
within Nova in line with the block storage encryption implementation provided
by Cinder where user selectable &lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/configuration/block-storage/volume-encryption.html#create-an-encrypted-volume-type"&gt;encrypted volume types&lt;/a&gt; are available.&lt;/p&gt;
&lt;p&gt;Note that this spec will only cover the high level changes to the API and
compute layers, implementation within specific virt drivers is left for
separate specs.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At present the only in-tree ephemeral storage encryption support is provided by
the libvirt virt driver when using the lvm imagebackend. The current
implementation provides basic operator controlled and configured host specific
support for ephemeral disk encryption at rest where all instances on a given
compute are forced to use encrypted ephemeral storage using the dm-crypt
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;This is not ideal and makes ephemeral storage encryption completely opaque
to the end user as opposed to the block storage encryption support provided by
Cinder where users are able to opt-in to using admin defined encrypted volume
types to ensure their storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally the current implementation uses a single symmetric key to encrypt
all ephemeral storage associated with the instance. As the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt; encryption
format is used there is no way to rotate this key in-place.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user I want to request that all of my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to pick how my ephemeral storage is encrypted
at rest through the selection of a specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to either enforce ephemeral encryption per flavor
or per image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an admin/operator I want to provide sane choices to my end users regarding
how their ephemeral storage is encrypted at rest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to indicate that my driver
supports ephemeral storage encryption using a specific encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a virt driver maintainer/developer I want to provide sane default
encryption format and options for users looking to encrypt their ephemeral
storage at rest. I want these associated with the encrypted storage until it
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To enable this new flavor extra specs, image properties and host configurables
will be introduced. These will control when and how ephemeral storage
encryption at rest is enabled for an instance.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The following &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt; image properties do not relate to if
an image is encrypted at rest within the Glance service. They only
relate to how ephemeral storage will be encrypted at rest when used by a
provisioned instance within Nova.&lt;/p&gt;
&lt;p&gt;Separate image properties have been documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/image-encryption.html"&gt;Glance image encryption&lt;/a&gt; and &lt;a class="reference external" href="https://specs.openstack.org/openstack/cinder-specs/specs/wallaby/image-encryption.html"&gt;Cinder image encryption&lt;/a&gt; specs to cover
how images can be encrypted at rest within Glance.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="allow-ephemeral-encryption-to-be-configured-by-flavor-image-or-config"&gt;
&lt;h3&gt;Allow ephemeral encryption to be configured by flavor, image or config&lt;/h3&gt;
&lt;p&gt;To enable ephemeral encryption per instance the following boolean based flavor
extra spec and image property will be introduced:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above will enable ephemeral storage encryption for an instance but does not
control the encryption format used or the associated options. For this the
following flavor extra specs, image properties and configurables will be
introduced.&lt;/p&gt;
&lt;p&gt;The encryption format used will be controlled by the following flavor extra
specs and image properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When neither of the above are provided but ephemeral encryption is still
requested an additional host configurable will be used to provide a default
format per compute, this will initially default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This could lead to requests against different clouds resulting in a different
ephemeral encryption format being used but as this is transparent to the end
user from within the instance it shouldn’t have any real impact.&lt;/p&gt;
&lt;p&gt;The format will be provided as a string that maps to a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; oslo.versionedobjects field value:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; for the plain dm-crypt format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt;  for the LUKSv1 format&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="blockdevicemapping-changes"&gt;
&lt;h3&gt;BlockDeviceMapping changes&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object will be extended to include the following
fields encapsulating some of the above information per ephemeral disk within
the instance:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple boolean to indicate if the block device is encrypted. This will
initially only be populated when ephemeral encryption is used but could
easily be used for encrypted volumes as well in the future.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;As the name suggests this will contain the UUID of the associated
encryption secret for the disk. The type of secret used here will be
specific to the encryption format and virt driver used, it should not be
assumed that this will always been an symmetric key as is currently the
case with all encrypted volumes provided by Cinder. For example, for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;luks&lt;/span&gt;&lt;/code&gt; based ephemeral storage this secret will be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;passphrase&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatType&lt;/span&gt;&lt;/code&gt; enum and associated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceEncryptionFormatTypeField&lt;/span&gt;&lt;/code&gt; field listing the encryption
format. The available options being kept in line with the constants
currently provided by os-brick and potentially merged in the future if both
can share these types and fields somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A simple unversioned dict of strings containing encryption options specific
to the virt driver implementation, underlying hypervisor and format being
used.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="populate-ephemeral-encryption-blockdevicemapping-attributes-during-build"&gt;
&lt;h3&gt;Populate ephemeral encryption BlockDeviceMapping attributes during build&lt;/h3&gt;
&lt;p&gt;When launching an instance with ephemeral encryption requested via either the
image or flavor the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping.encrypted&lt;/span&gt;&lt;/code&gt; attribute will be set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; record with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destination_type&lt;/span&gt;&lt;/code&gt;
value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt;. This will happen after the original API BDM dicts have been
transformed into objects within the Compute API but before scheduling the
instance(s).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; attribute will also take its’ value from the image or
flavor if provided. Any differences or conflicts between the image and flavor
for this will raise a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;409&lt;/span&gt; &lt;span class="pre"&gt;Conflict&lt;/span&gt;&lt;/code&gt; error being raised by the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-new-compatibility-traits"&gt;
&lt;h3&gt;Introduce new compatibility traits&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; compute compatibility trait will be
added to os-traits and reported by virt drivers to indicate overall support for
ephemeral storage encryption using this new approach. This trait will always be
used by pre-filter outlined in the following section when ephemeral encryption
has been requested, regardless of any format being specified in the request,
allowing the compute that eventually handles the request to select a format it
supports using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/default_format&lt;/span&gt;&lt;/code&gt;
configurable.&lt;/p&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compute compatibility traits will
be added to os-traits and reported by virt drivers to indicate support for
specific ephemeral storage encryption formats. For example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKSV2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_PLAIN&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These traits will only be used alongside the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
trait when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; image property or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption_format&lt;/span&gt;&lt;/code&gt; extra spec have been provided in the initial
request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="introduce-an-ephemeral-encryption-request-pre-filter"&gt;
&lt;h3&gt;Introduce an ephemeral encryption request pre-filter&lt;/h3&gt;
&lt;p&gt;A new pre-filter will be introduced that adds the above traits as required to
the request spec when the aforementioned image properties or flavor extra specs
are provided. As outlined above this will always include the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; trait when ephemeral encryption has been
requested and may optionally include one of the format specific traits if a
format is included in the request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="expose-ephemeral-encryption-attributes-via-block-device-info"&gt;
&lt;h3&gt;Expose ephemeral encryption attributes via block_device_info&lt;/h3&gt;
&lt;p&gt;Once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; objects have been updated and the instance
scheduled to a compute the objects are transformed once again into a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict understood by the virt layer that at present
contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;root_device_name&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The root device path used by the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemerals&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverEphemeralBlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the
ephemeral disks attached to the instance. Note this does not include the
initial image based disk used by the instance that is classified as an
ephemeral disk in terms of the ephemeral encryption feature.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverVol*BlockDevice&lt;/span&gt;&lt;/code&gt; dict objects detailing the volume based
disks attached to the instance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverSwapBlockDevice&lt;/span&gt;&lt;/code&gt; dict object detailing the swap
device.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"root_device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ephemerals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"guest_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"block_device_mapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"swap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swap_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"device_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As noted above &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; does not provide a complete overview of
the storage associated with an instance. In order for it to be useful in the
context of ephemeral storage encryption we would need to extend the dict to
always include information relating to local image based disks.&lt;/p&gt;
&lt;p&gt;As such a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt; dict class will be introduced covering
image based block devices and provided to the virt layer via an additional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; key within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict when the instance uses such
a disk. As with the other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; dict classes this will proxy
access to the underlying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object allowing the virt layer
to lookup the previously listed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_*&lt;/span&gt;&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;While outside the scope of this spec the above highlights a huge amount of
complexity and technical debt still residing in the codebase around how storage
configurations are handled between the different layers. In the long term we
should plan to remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and replace it with direct access
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; based objects ensuring the entire configuration is
always exposed to the virt layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="report-that-a-disk-is-encrypted-at-rest-through-the-metadata-api"&gt;
&lt;h3&gt;Report that a disk is encrypted at rest through the metadata API&lt;/h3&gt;
&lt;p&gt;Extend the metadata API so that users can confirm that their ephemeral storage
is encrypted at rest through the metadata API, accessible from within their
instance.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"devices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0000:00:02.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"mac"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00:11:22:33:44:55"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/vda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0:0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk-vol-2352423"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"baz"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This should also be extended to cover disks provided by encrypted volumes but
this is obviously out of scope for this implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="block-resize-between-flavors-with-different-hw-ephemeral-encryption-settings"&gt;
&lt;h3&gt;Block resize between flavors with different hw:ephemeral_encryption settings&lt;/h3&gt;
&lt;p&gt;Ephemeral data is expected to persist through a resize and as such any resize
between flavors that differed in their configuration of ephemeral encryption
(one enabled, another disabled or formats etc) would cause us to convert this
data in place. This isn’t trivial and so for this initial implementation
resizing between flavors that differ will be blocked.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provide-a-migration-path-from-the-legacy-implementation"&gt;
&lt;h3&gt;Provide a migration path from the legacy implementation&lt;/h3&gt;
&lt;p&gt;New &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands will be introduced to migrate
any instances using the legacy libvirt virt driver implementation ahead of the
removal of this in a future release.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command will ensure that any existing instances with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set will have their associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt;
records updated to reference said secret key, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;plain&lt;/span&gt;&lt;/code&gt; encryption format
and configured options on the host before clearing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally the libvirt virt driver will also attempt to migrate instances
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set during spawn. This should allow at least some
of the instances to be moved during the W release ahead of X.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will simply report on the existence of any
instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ephemeral_key_uuid&lt;/span&gt;&lt;/code&gt; set that do not have the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; attributes enabled etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deprecate-the-now-legacy-implementation"&gt;
&lt;h3&gt;Deprecate the now legacy implementation&lt;/h3&gt;
&lt;p&gt;The legacy implementation within the libvirt virt driver will be deprecated for
removal in a future release once the ability to migrate is in place.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See above for the various flavor extra spec, image property,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverBlockDevice&lt;/span&gt;&lt;/code&gt; object changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor extra specs and image property validation will be introduced for the
any ephemeral encryption provided options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to resize between flavors that differ in their ephemeral encryption
options will be rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attempts to rebuild between images that differ in their ephemeral encryption
options will be allowed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The metadata API will be changed to allow users to determine if their
ephemeral storage is encrypted as discussed above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;p&gt;Additionally this should allow additional virt drivers to support ephemeral
storage encryption while also allowing the libvirt virt driver to increase
coverage of the feature across more imagebackends such as qcow2 and rbd.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The additional pre-filter will add a small amount of overhead when scheduling
instances but this should fail fast if ephemeral encryption is not requested
through the image or flavor.&lt;/p&gt;
&lt;p&gt;The performance impact of increased use of ephemeral storage encryption by
instances is left to be discussed in the virt driver specific specs as this
will vary between hypervisors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver developers will be able to indicate support for specific ephemeral
storage encryption formats using the newly introduced compute compatibility
traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The compute traits should ensure that requests to schedule instances using
ephemeral storage encryption with mixed computes (N-1 and N) will work during a
rolling upgrade.&lt;/p&gt;
&lt;p&gt;As discussed earlier in the spec future upgrades will need to provide a path
for existing ephemeral storage encryption users to migrate from the legacy
implementation. This should be trivial but may require an additional grenade
based job in CI during the W cycle to prove out the migration path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_ephemeral_encryption*&lt;/span&gt;&lt;/code&gt; image properties and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:ephemeral_encryption&lt;/span&gt;&lt;/code&gt; flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_$FORMAT&lt;/span&gt;&lt;/code&gt; compatibility traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encrypted&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt; attributes to the
BlockDeviceMapping Object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wire up the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BlockDeviceMapping&lt;/span&gt;&lt;/code&gt; object attributes through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Driver*BlockDevice&lt;/span&gt;&lt;/code&gt; layer and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; dict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Report ephemeral storage encryption through the metadata API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; commands to allow existing
users to migrate to this new implementation. This should however be blocked
outside of testing until a virt driver implementation is landed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate all of the above in functional tests ahead of any virt driver
implementation landing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;At present without a virt driver implementation this will be tested entirely
within our unit and functional test suites.&lt;/p&gt;
&lt;p&gt;Once a virt driver implementation is available additional integration tests in
Tempest and whitebox tests can be written.&lt;/p&gt;
&lt;p&gt;Testing of the migration path from the legacy implementation will require an
additional grenade job but this will require the libvirt virt driver
implementation to be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new host configurables, flavor extra specs and image properties should be
documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New user documentation should be written covering the overall use of the
feature from a Nova point of view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around &lt;cite&gt;BlockDeviceMapping&lt;/cite&gt; objects etc should be
updated to make note of the new encryption attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Smartnic Management Overall Design</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/sriov-smartnic-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/sriov-smartnic-support"&gt;https://blueprints.launchpad.net/nova/+spec/sriov-smartnic-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes an overall design for smartnic management which will involve
Nova, Neutron and Cyborg changes. In this spec, we will introduce how to manage
the smartnic’s lifecycle, and how to attach a smartnic to the VM.
This spec aims at supporting VF management, the PF management is out-of-scope.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nowadays, various devices are made to run specific workloads which will free up
CPU resources. Smart-nic is a network device that can be used to offload the
network-related workload. It goes beyond simple connectivity and implements
network traffic processing on the NIC that would necessarily be performed by
the CPU in the case of a conventional NIC.&lt;/p&gt;
&lt;p&gt;In the current design, OpenStack can not manage and schedule a smart-nic in
terms of supported features and readable traits automatically.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Users want to boot up a VM with a specific port which is associated with a
smartnic resource managed by Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users want to boot vms that leverage pre-programmed functionality to offload
their workload to a smart-nic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are multiple projects(Nova, Neutron, Cyborg, and Placement) involved in
this feature.&lt;/p&gt;
&lt;section id="workflow"&gt;
&lt;h3&gt;Workflow&lt;/h3&gt;
&lt;p&gt;This workflow describes the basic operation to boot a VM with pre-programmed
nic.
The workflow can be divided into two parts:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Device discovery and report.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interaction when booting a VM.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="device-discovery"&gt;
&lt;h4&gt;Device discovery&lt;/h4&gt;
&lt;p&gt;Cyborg should implement a driver that the cyborg-agent can invoke periodically
to discover the smartnic resources. We will explain this part in detail in
Cyborg spec, please refer to &lt;a class="reference external" href="https://review.opendev.org/#/c/759545/"&gt;https://review.opendev.org/#/c/759545/&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="device-information-report"&gt;
&lt;h4&gt;Device information report&lt;/h4&gt;
&lt;section id="how-to-report-physnet-trait"&gt;
&lt;h5&gt;How to report physnet trait&lt;/h5&gt;
&lt;p&gt;As we know, Neutron has a config option physical_device_mappings indicating the
mapping relation between physical_network and network_device. Admin need to
maintain another configuration file (Please refer to 1 in the flowchart) that
contains the device’s name and the physical network name this device associate
to.
In this way, the Cyborg driver can directly read from this file and add a
physical network as a trait when reporting to Placement. The admin is
responsible to keep Cyborg’s and Neutron’s config file consistent, otherwise,
there will be a configuration conflict.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="co-existence-with-neutron-s-guaranteed-minimum-bandwidth-1-feature"&gt;
&lt;h5&gt;Co-existence with Neutron’s Guaranteed Minimum Bandwidth &lt;a class="footnote-reference brackets" href="#id14" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; Feature&lt;/h5&gt;
&lt;p&gt;According to Wallaby PTG discussion &lt;a class="footnote-reference brackets" href="#id15" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and the following discussions &lt;a class="footnote-reference brackets" href="#id16" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
in the community, we propose to not support co-existence with Neutron’s
Guaranteed Minimum Bandwidth Feature for the same physical device at the
first step, which means that one physical device can only be configured by
Cyborg or by Neutron’s QoS feature if it is enabled.&lt;/p&gt;
&lt;p&gt;The following flowchart illustrates the workflow during device discovery and
report:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;  &lt;span class="o"&gt;+----------------+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;cyborg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--------+-------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;+-------------+&lt;/span&gt;        &lt;span class="o"&gt;+-------------+&lt;/span&gt;
&lt;span class="o"&gt;+----------|---------+&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;cyborg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;conductor&lt;/span&gt;  &lt;span class="o"&gt;|-----------&amp;gt;|&lt;/span&gt;  &lt;span class="n"&gt;Placement&lt;/span&gt;  &lt;span class="o"&gt;|&amp;lt;-------|&lt;/span&gt;   &lt;span class="n"&gt;Neutron&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------|---------+&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;+-------------+&lt;/span&gt;        &lt;span class="o"&gt;+-------------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;+------------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;+------&amp;gt;|&lt;/span&gt;  &lt;span class="n"&gt;Cyborg&lt;/span&gt; &lt;span class="n"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--------|-------+&lt;/span&gt;               &lt;span class="o"&gt;+------------+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;cyborg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--------|-------+&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;
           &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;+----------------+&lt;/span&gt;
  &lt;span class="o"&gt;+--------|-------+&lt;/span&gt;     &lt;span class="mi"&gt;1&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;  &lt;span class="o"&gt;|&amp;lt;----------|&lt;/span&gt;  &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+----------------+&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
                               &lt;span class="o"&gt;+----------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="interaction-when-booting-the-vm"&gt;
&lt;h4&gt;Interaction when booting the VM&lt;/h4&gt;
&lt;p&gt;Currently, Nova can interact with Cyborg to boot up a VM with an accelerator
like FPGA, GPU. And other operations such as hard/soft reboot, pause/unpause
are also supported. But there is no mechanism to let Nova boot up a VM with a
nic associated with a specific network. To implement this, it requires
Nova, Cyborg, and Neutron change. And this spec also covers the scenario about
reboot/pause/stop/start and other operations.&lt;/p&gt;
&lt;p&gt;Here we take the “boot a VM” scenario as an example. Assuming that Cyborg has
reported the nic resources and related traits correctly.
The workflow is proposed as the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt; &lt;span class="o"&gt;+-----------+&lt;/span&gt;      &lt;span class="o"&gt;+-----------+&lt;/span&gt; &lt;span class="o"&gt;+-----------+&lt;/span&gt;   &lt;span class="o"&gt;+-----------+&lt;/span&gt;   &lt;span class="o"&gt;+---------+&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;admin&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Neutron&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;Nova&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Placement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Cyborg&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="o"&gt;+-----|-----+&lt;/span&gt;      &lt;span class="o"&gt;+-----|-----+&lt;/span&gt; &lt;span class="o"&gt;+-----|-----+&lt;/span&gt;   &lt;span class="o"&gt;+-----|-----+&lt;/span&gt;   &lt;span class="o"&gt;+-------+-+&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;|-----------------------------------------------------------------&amp;gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----|-----+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|------------------&amp;gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|--------------------------------&amp;gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                       &lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;physnet&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;

                          &lt;span class="o"&gt;|&amp;lt;------------|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                                                 &lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;-------------------------------&amp;gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="n"&gt;sheduling&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;-------------&amp;gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mf"&gt;7.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PCI&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;-------------------------------&amp;gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mf"&gt;8.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&amp;lt;------------|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|-----+&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;9.&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="n"&gt;SRIOV&lt;/span&gt; &lt;span class="n"&gt;VIF&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;libvirt&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt; &lt;span class="n"&gt;section&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&amp;lt;----+&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
                          &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;1. Firstly, admin needs to create a device profile that contains the smartnic’s
description such as resource class, and traits. The CLI are already supported
as the following:&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;GRP=”[{“resources:CUSTOM_NIC”: “1”,”trait:CUSTOM_GTV1”:”required”}]”
openstack accelerator device profile create sriov_dp1 $GRP&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;2. Secondly, user needs to create a port by passing device profile as a
parameter. Related API needs to be added to operate this. And also,
Neutron need to add a new vnic-type for the nic managed by Cyborg, we can name
it “cyborg” here. For example, we can create a port by: &lt;cite&gt;openstack port
create –network providernet –vnic-type cyborg –device-profile sriov-dp1
sriov_port1&lt;/cite&gt; in which &lt;cite&gt;sriov-dp1&lt;/cite&gt; is the device profile created at the first
step.
The request body is the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"sriov-port1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"network_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a87cc70a-3e15-4acf-8205-9b711a3531b7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"vnic_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"cyborg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"device_profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"sriov_dp1"&lt;/span&gt; &lt;span class="c1"&gt;# new extension contains device profile&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;3. Thirdly, user can boot up a VM by:
&lt;cite&gt;openstack server create –image image-uuid -flavor flavor-name  –nic
port-id=sriov_port1 test_vm1&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;4. Nova interacts with Neutron to get port’s details, including vnic type,
neutwork_id, physical network, etc.&lt;/p&gt;
&lt;p&gt;5. If the vnic type is “cyborg”, then Nova need to extract the “device_profile”
extension of sriov_port1, and call Cyborg API to get details of this
device_profile &lt;a class="footnote-reference brackets" href="#id17" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, the ARQ creation is also in this step.&lt;/p&gt;
&lt;p&gt;6. In step 4, Nova has fetched the physical network from Neutron, now Nova need
to convert it into Placement’s trait format and save it in port’s resource
request field if vnic type is “cyborg”. Then Nova need to merge the resource
class/trait obtained from Cyborg’s device profile and the port resource request
into a one single request group. And this request group will be merged into
request_spec which will be used in reboot/pause/start/stop and other supported
operations. After that, Nova schedules the VM to an available compute node
who matches all requested resources.&lt;/p&gt;
&lt;p&gt;7. After scheduling, Nova needs to call Cyborg to bind the ARQ with port id
and return attach_handle which contains the device’s info such as PCI
address.&lt;/p&gt;
&lt;p&gt;8. Nova also needs to tell Neutron to update the port binding’s info
in this step.&lt;/p&gt;
&lt;p&gt;9. Libvirt driver need to insert SRIOV nic info to the XML
section.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="api-calls"&gt;
&lt;h4&gt;API calls&lt;/h4&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Nova calls Neutron to get port details.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;request URL: /v2.0/ports/{port_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;response example(the new extension &lt;cite&gt;device_profile&lt;/cite&gt; should be returned):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
      &lt;span class="s2"&gt;"binding_profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"sriov-port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"network_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a87cc70a-3e15-4acf-8205-9b711a3531b7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"qos_network_policy_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"174dd0c1-a4eb-49d4-a807-ae80246d82f4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"qos_policy_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"29d5e02e-d5ab-4929-bee4-4a9fc12e22ae"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"device_profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"sriov-dp1"&lt;/span&gt; &lt;span class="c1"&gt;# new extension&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Nova calls Cyborg to get device profile’s details. &lt;a class="footnote-reference brackets" href="#id18" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova calls Cyborg to create and bind ARQs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create ARQ &lt;a class="footnote-reference brackets" href="#id19" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind ARQ &lt;a class="footnote-reference brackets" href="#id20" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;Nova call Neutron to update port binding profile with interface info. &lt;a class="footnote-reference brackets" href="#id21" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="neutron"&gt;
&lt;h3&gt;Neutron&lt;/h3&gt;
&lt;p&gt;In Neutron side, a new vnic type “cyborg” need to be added, as well as a new
port extension “device_profile”. Please refer to Neutron’s RFE &lt;a class="footnote-reference brackets" href="#id22" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; for
details.&lt;/p&gt;
&lt;p&gt;The proposed change includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new vnic type “cyborg” indicating the port associated with device
managed by Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define device profile extension for port in neutorn lib.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement device profile extension for port in Neutron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From DB side, we need to add a new table to store the mapping relation
between port and device_profile:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+---------------------------------------+------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;port_uuid&lt;/span&gt;                             &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;device_profile&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+=======================================+========================+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="n"&gt;f78856&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f73&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;cf4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bcd0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1389086&lt;/span&gt;&lt;span class="n"&gt;eb038&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sriov_dev_profile&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+---------------------------------------+------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please refer to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Port resource request definition &lt;a class="footnote-reference brackets" href="#id23" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;10&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;neutron-lib port-resource-request Commits &lt;a class="footnote-reference brackets" href="#id24" id="id11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;11&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;neutron plugin port-resource-request Commits &lt;a class="footnote-reference brackets" href="#id25" id="id12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;12&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="nova"&gt;
&lt;h3&gt;Nova&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova API: Nova calls Neutron API to get port details, including vnic type,
physical network etc.
“device_profile” should be returned as the return value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API: Nova need to check if vnic type is “cyborg”. If so, Nova will get
the device profile’s name from neutron port and call Cyborg API to get the
details of this device profile. Meanwhile, Nova need to generate a trait
for physical network, for example, Nova get “physnet1” as the physical
network from Neutorn, the trait should looks like “CUSTOM_PHYSNET_PHYSNET1”,
which is consistent with what Cyborg reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova API: Once Nova gets all resource classes and traits, Nova should check
if a RequestGroup is created with port_resource_request, if so, we should add
resource and traits to this request group, if not, we should generate a new
resource group. Nova should have one single request_group to schedule to a
single nic resource provider &lt;a class="footnote-reference brackets" href="#id26" id="id13" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;13&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This request_group store the requested
resource information used by the scheduler, and other operations, such as
reboot/pause/unpause/start/stop, will use this request_group to do the
scheduling as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova Compute: Nova should update port binding profile with sriov nic’s info
(such as pci adderess etc), so that libvirt driver can generete related xml
section.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="cyborg"&gt;
&lt;h3&gt;Cyborg&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A new driver needs to be added in Cyborg in order to discover, program and
bind the device. More details is in the Cyborg spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cyborg should improve current bind ARQ API to support binding an ARQ to the
port ID.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cyborg needs to implement a device config file to configure the nic’s
name, pci address, physnet name, etc, which are used for Cyborg driver to
generate resource provider, trait, etc.&lt;/p&gt;
&lt;div class="highlight-RST notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;[dev-name]
pci_address=0000:18:00.0
function_name=GTPv1
physnet=physnet1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="who-reports-physnet-trait"&gt;
&lt;h4&gt;Who reports physnet trait&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Placement CLI to add trait.&lt;/p&gt;
&lt;p&gt;Admin need to add physnet trait to resource provider manually, this will be
done after Cyborg reports resource to Placement. It will cause redundant
Placement API call as well.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron report trait for the resource provider created by Cyborg.&lt;/p&gt;
&lt;p&gt;In this way, Neutron should firstly get a resource provider created by Cyborg
by Placement API, and Neutron also need to find the right physnet tratis
according to nic’s resource, which requires more changes in Neutron.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let Neutron create RP and physnet trait.&lt;/p&gt;
&lt;p&gt;As we know, Neutron will create RP and related traits when minimum bandwidth
QoS is configured. We propose that Neutron could always report RP and physnet
traits all the time, no matter the bandwidth qos configured or not. In this
way, Cyborg will just find the RP created by Neutron by using some name
convention, and add accelerator-related traits to this RP.&lt;/p&gt;
&lt;p&gt;But we should consider how the RP tree structure look like when Neutron
report it, should it be directly under compute node RP, or still under Agent
RP like bandwidth qos feature does.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="how-nova-generate-request-spec-with-request-device"&gt;
&lt;h4&gt;How Nova generate request_spec with request device&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Neutron calls Cyborg API to get device profile details and merge all RC and
trait into port_resource_reqeust, then return to Nova.&lt;/p&gt;
&lt;p&gt;It requires Neutron changes to interact with Cyborg, which seems that Cyborg
is a sub-component for Neutron. It’s better to let Nova interact with Cyborg
and Neutron equally.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a new DeviceProfileRequest to store the device profile’s request
group, and pass it as a new parameter when Nova generates request_spec.&lt;/p&gt;
&lt;p&gt;It seems to be redundant to have a new request object.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="others"&gt;
&lt;h4&gt;Others&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cyborg provides its own SRIOV ML2 driver for the NICs it supports.&lt;/p&gt;
&lt;p&gt;Cyborg maintains a Neutron plugin driver that exceeds Cyborg project’s scope.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ARQ’s consumer could be an instance instead of port.&lt;/p&gt;
&lt;p&gt;May cause the confusion with current Nova-Cyborg integration(No Neutron
involvement). But it seems a choice, it’s open for comments and suggestions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;New table &lt;cite&gt;device_profile&lt;/cite&gt; needs to be added in Neutron DB.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new extension ‘device_profile’ will be added in Neutron port, Neutron API
need changes. Neutron API should also forbid user to modify ‘device_profile’
field once the port is bound with one instance(Neutorn API need to check the
binding:host-id before updating the ‘device profile’ field.). This
modification is only allowed when the port is unbound.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind ARQ API should be improved to support binding an ARQ with port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change Nova APIs for more operation supports. We plan to support
create/delete, start/stop, pause/unpause, suspend/resume, shelve/unshelve,
rebuild, reboot, evacuate operations for a VM having an “cyborg” vnic type
port.
The rest of the lifecycle operations will be rejected now with HTTP 403 Error
code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Yongli He(&lt;a class="reference external" href="mailto:yongli.he%40intel.com"&gt;yongli&lt;span&gt;.&lt;/span&gt;he&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Xinran Wang(&lt;a class="reference external" href="mailto:xin-ran.wang%40intel.com"&gt;xin-ran&lt;span&gt;.&lt;/span&gt;wang&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new port extension in Neutron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a new driver for specific nic in Cyborg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a configuration file in Cyborg to handle physnet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parse and merge request into request spec in Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind ARQ to port id and update port binding profile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-use the current sriov nic xml generation code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Need to add UT in the involved project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional test in Nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest test in Nova if necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest test in cyborg-tempest-plugin.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Need to add documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id14" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html"&gt;https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/nova-wallaby-ptg"&gt;https://etherpad.opendev.org/p/nova-wallaby-ptg&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2020-11-09.log.html#t2020-11-09T05:48:48"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2020-11-09.log.html#t2020-11-09T05:48:48&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id17" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html?expanded=#list-device-profiles"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html?expanded=#list-device-profiles&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id18" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html#list-device-profiles"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html#list-device-profiles&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id19" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html#create-accelerator-requests"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html#create-accelerator-requests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id20" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/accelerator/v2/index.html#update-accelerator-requests"&gt;https://docs.openstack.org/api-ref/accelerator/v2/index.html#update-accelerator-requests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id21" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/network/v2/#update-port"&gt;https://docs.openstack.org/api-ref/network/v2/#update-port&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id22" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1906603"&gt;https://bugs.launchpad.net/neutron/+bug/1906603&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id23" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;10&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/508149/14/specs/rocky/minimum-bandwidth-allocation-placement-api.rst"&gt;https://review.opendev.org/#/c/508149/14/specs/rocky/minimum-bandwidth-allocation-placement-api.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id24" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id11"&gt;11&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron-lib/search?q=port-resource-request&amp;amp;type=Commits"&gt;https://github.com/openstack/neutron-lib/search?q=port-resource-request&amp;amp;type=Commits&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id25" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id12"&gt;12&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/search?q=port-resource-request&amp;amp;type=Commits"&gt;https://github.com/openstack/neutron/search?q=port-resource-request&amp;amp;type=Commits&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id26" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id13"&gt;13&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/placement/latest/user/provider-tree.html#granular-resource-requests"&gt;https://docs.openstack.org/placement/latest/user/provider-tree.html#granular-resource-requests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id27"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Allow Secure Boot (SB) for QEMU- and KVM-based guests</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/allow-secure-boot-for-qemu-kvm-guests.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/allow-secure-boot-for-qemu-kvm-guests"&gt;https://blueprints.launchpad.net/nova/+spec/allow-secure-boot-for-qemu-kvm-guests&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Today, Nova’s libvirt driver only has support for generic UEFI boot but
not Secure Boot (the goal of which is to: “make sure no unsigned kernel
code runs on the machine”) for QEMU and KVM guests.  Secure Boot
protects guests from boot-time malware and validates that the code
executed by the guest firmware is trusted.&lt;/p&gt;
&lt;p&gt;More precisely, the libvirt driver has the OVMF (the open source
implementation of UEFI for virtual machines) binary file’s path
hard-coded in a variable:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;DEFAULT_UEFI_LOADER_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"x86_64"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/usr/share/OVMF/OVMF_CODE.fd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"aarch64"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/usr/share/AAVMF/AAVMF_CODE.fd"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The above only provides generic UEFI boot &lt;a class="footnote-reference brackets" href="#id15" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, but not Secure Boot.
Also it is not robust to hardcode OVMF binary file paths this way.&lt;/p&gt;
&lt;p&gt;This specification proposes to extend the existing support for UEFI boot
in Nova’s libvirt driver to also support Secure Boot.  Refer to the
sections &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt; and &lt;a class="reference internal" href="#work-items"&gt;Work items&lt;/a&gt; for what needs to be done to
support the Secure Boot for KVM / QEMU guests.  In this spec, we focus only on
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt; architecture.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Nova’s Hyper-V driver already has support for Secure Boot; it
was added in commit: 29dab99 – “Hyper-V: Adds Hyper-V UEFI
Secure Boot” &lt;a class="footnote-reference brackets" href="#id16" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;A non-exhaustive list:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Protect the Nova instances being launched from boot-time malware from
the guest side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secure Boot will prevent the Nova instance from running untrusted code
by requiring a trusted signature on UEFI binaries. For more details,
refer to the “Testing Secure Boot” guide here &lt;a class="footnote-reference brackets" href="#id17" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secure Boot will allow trustworthy code in Nova instances to: (a)
enable the Secure Boot operational mode (for protecting itself), and;
(b) prevent malicious code in the guests from circumventing the actual
security of the Secure Boot operational mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And, as a refresher, benefits of using OVMF are listed in the
“Motivation” section of the OVMF white paper &lt;a class="footnote-reference brackets" href="#id18" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.  And for a more
detailed treatment of Secure Boot, refer to this &lt;a class="footnote-reference brackets" href="#id19" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To allow Secure Boot for KVM and QEMU guests, the following are the
rough set of planned changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Reuse the existing Nova metadata property, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_secure_boot&lt;/span&gt;&lt;/code&gt; (added
for Hyper-V support) to allow user to request Secure Boot support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the initial implemetation, Nova will only support the default UEFI
keys, which will work with most distributions (Debian, Ubuntu, SUSE,
Fedora, CentOS and RHEL)—as they provide a variables file (“VARS”)
with default UEFI keys enrolled.  (If you don’t trust the default UEFI
keys, then it is equivalent to you not trusting the filesystem where
your compute node is running.)  If later desired, we can reuse the
existing image metadata property, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_secure_boot_signature&lt;/span&gt;&lt;/code&gt; that
lets you specify bootloader’s signature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make Nova use libvirt’s interface for auto-selecting firmware
binaries; this was added in libvirt 6.0 &lt;a class="footnote-reference brackets" href="#id20" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.  Why?&lt;/p&gt;
&lt;p&gt;Problem: Today, Nova does not have a sensible way of knowing which
firmware binary to select.  All it sees is the firmware binary path
that is hard-coded, which is ugly and fragile.  Not least of all, it
is non-trivial to tell whether that binary supports Secure Boot or
not.&lt;/p&gt;
&lt;p&gt;Solution: Here is where libvirt’s firmware auto-selection comes into
the picture.  It takes advantage of a lot of work done in QEMU and
OVMF, and fixes the above mentioned problem by providing a robust
interface.  As in, libvirt can now pick up the &lt;em&gt;correct&lt;/em&gt; OVMF binary,
with Secure Boot (SB) and System Management Mode (SMM) enabled, with a
convenient XML config:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt; &lt;span class="n"&gt;firmware&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'efi'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="n"&gt;secure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The version requirements should be satisifed for ‘Wallaby’ release, as
Nova has announced it will have these libvirt and QEMU versions:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NEXT_MIN_LIBVIRT_VERSION&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;(6,&lt;/span&gt; &lt;span class="pre"&gt;0,&lt;/span&gt; &lt;span class="pre"&gt;0)&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NEXT_MIN_QEMU_VERSION&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt;
&lt;span class="pre"&gt;(4,&lt;/span&gt; &lt;span class="pre"&gt;2,&lt;/span&gt; &lt;span class="pre"&gt;0)&lt;/span&gt;&lt;/code&gt;.  This allows us to use libvirt’s formal interface that
allows auto-selecting firmware binaries—this also means relatively
much less “scaffolding code” in Nova.&lt;/p&gt;
&lt;p&gt;The above libvirt feature takes advantage of QEMU’s firmware
description schema &lt;a class="footnote-reference brackets" href="#id21" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make Nova programatically query the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;getDomainCapabilities()&lt;/span&gt;&lt;/code&gt; API to
check if libvirt supports the relevant Secure Boot-related features.
Introduce a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_has_uefi_secure_boot_support()&lt;/span&gt;&lt;/code&gt; method to check if libvirt
can support the feature.  This can be done by checking for the
presence of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;efi&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;secure&lt;/span&gt;&lt;/code&gt; XML attributes from the output of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$getDomainCapabilities()&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the initial implementation, there will be no scheduler support to
isolate hosts that are not Secure Boot-capable, similar to existing
basic UEFI boot support.  Nova will error out if the host hypervisor
does not support Secure Boot.&lt;/p&gt;
&lt;p&gt;This can be done via introducing a “trait” to avoid selecting hosts
that do not have support for Secure Boot.  It also enables other
use cases such as filtering hosts by isolating “aggregates” &lt;a class="footnote-reference brackets" href="#id22" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="low-level-background-on-different-kinds-of-ovmf-builds"&gt;
&lt;h3&gt;Low-level background on different kinds of OVMF builds&lt;/h3&gt;
&lt;p&gt;[Thanks: Laszlo Ersek, OVMF maintainer, for the below discussion.  I
added, with permission, a good chunk of verbatim text from Laszlo.]&lt;/p&gt;
&lt;p&gt;One feature that can be built into OVMF is the “Secure Boot Feature”.
This is different from the operational mode called “Secure Boot” (SB).
If the firmware contains the feature, then the guest can enable or
disable the operational mode. If the firmware does not contain the
feature, then the guest cannot enable the operational mode.&lt;/p&gt;
&lt;p&gt;Another feature that can be built into OVMF is called “SMM” (Secure
Management Mode). This means a driver stack that consists of a set of
privileged drivers that run in SMM, and another, interfacing set of
unprivileged drivers that only format requests for the privileged half,
and parse responses from it. Once the SMM feature is built into OVMF,
then SMM emulation by the QEMU platform is &lt;em&gt;non-optional&lt;/em&gt;, it is
required.&lt;/p&gt;
&lt;p&gt;The Secure Boot Feature and the SMM feature stack are orthogonal. You
can build OVMF in all four configurations. However, if you want to allow
trustworthy code in your guests to enable the Secure Boot operational
mode (for protecting itself), and &lt;em&gt;also&lt;/em&gt; want to prevent malicious code
in your guests from &lt;em&gt;circumventing&lt;/em&gt; the actual security of the Secure
Boot operational mode, then you have to build &lt;em&gt;both&lt;/em&gt; features into OVMF.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Different distributions ship different kinds of builds.  E.g.
Fedora ships both variants of OVMF firmware binaries: one
without either SB or SMM, and the other with both SB or SMM.
Other distributions ship different builds as well, and under
different pathnames.  Even if they ship an SB+SMM OVMF build,
the path name for the firmware binary may be different.&lt;/p&gt;
&lt;p&gt;Thankfully, Nova does not need to work out the OVMF binary
paths.  This is handled by a combination of (a) Linux
distributions shipping the firmware descriptor files (small
JSON files that describe details about UEFI firmware binaries,
such as the fimware binary path, its architecture, supported
machine type, NVRAM template) with EDK2/OVMF; and (b) libvirt
&amp;gt;=5.3, to take advantage of the said firmware descriptor
files.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="ovmf-binary-files-and-variable-store-vars-file-paths"&gt;
&lt;h3&gt;OVMF binary files and variable store (“VARS”) file paths&lt;/h3&gt;
&lt;p&gt;Each distribution has its &lt;em&gt;own&lt;/em&gt; (but slightly different) path name of
OVMF:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;SUSE:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;package name: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-ovmf-x86_64&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/qemu/ovmf-x86_64-opensuse-code.bin&lt;/span&gt;&lt;/code&gt; is the firmware
binary built with SB and SMM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/qemu/ovmf-x86_64-opensuse-vars.bin&lt;/span&gt;&lt;/code&gt; is the variable
store template that matches the above binary&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Fedora:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;package name: “edk2-ovmf” (x86_64)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/edk2/ovmf/OVMF_CODE.fd&lt;/span&gt;&lt;/code&gt; is a firmware binary built
without either SB or SMM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd&lt;/span&gt;&lt;/code&gt; is a firmware
binary built with both SB and SMM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/edk2/ovmf/OVMF_VARS.fd&lt;/span&gt;&lt;/code&gt; is the variable store
template that matches both of the above binaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd&lt;/span&gt;&lt;/code&gt; is the variable store
template &lt;em&gt;with&lt;/em&gt; the default UEFI keys enrolled&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;RHEL-7.6 and RHEL-8:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;package name: “ovmf” (x86_64)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/OVMF/OVMF_CODE.secboot.fd&lt;/span&gt;&lt;/code&gt; is the firmware binary,
built with SB plus SMM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/OVMF/OVMF_VARS.secboot.fd&lt;/span&gt;&lt;/code&gt; is the matching variable
store template&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Debian (Buster) :&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;package name: “ovmf” (x86_64)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/share/OVMF/OVMF_CODE.fd&lt;/span&gt;&lt;/code&gt; is the firmware binary built with
SB plus SMM.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Ubuntu (Eoan):&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;package name: “ovmf” (x86_64)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the Eoan release also ships the firmware descriptor files we need
via EDK2 package (refer below)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is one of the tricky parts, but thankfully, the libvirt release 5.2
vastly simplifies the OVMF file name handling — by providing an
interface to auto-select firmware (which in turn, takes advantage of the
firmware descriptor files from QEMU (provided by QEMU 2.9 and above).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;With this feature, KVM- and QEMU-based Nova instances can get Secure
Boot support.  Thus protecting the guests from boot-time malware, and
ensures the code that the firmware executes only trusted code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;No cold or live migration impact; libvirt has the necessary safeguards
in place to handle.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;To use this feature, the following are the version requirements:
QEMU &amp;gt;=4.1.0, libvirt &amp;gt;=5.3, OVMF/EDK2 packages shipping the JSON
descriptor files.  Details in the &lt;a class="reference internal" href="#dependencies"&gt;Dependencies&lt;/a&gt; section.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Kashyap Chamarthy &amp;lt;&lt;a class="reference external" href="mailto:kchamart%40redhat.com"&gt;kchamart&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Taking the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt; architecture as an example here.  The following
are the work items for enabling Secure Boot support for QEMU and KVM
guests:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Make sure Nova configures the SMM (System Management Mode) hypervisor
feature in the guest XML when Secure Boot is requested:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;smm&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'on'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that when using libvirt’s firmware auto-selection feature,
libvirt will auto-add the SMM feature when starting the guest when SB
is requested, because SMM and SB go hand-in-hand.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure the OVMF &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;loader&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nvram&lt;/span&gt;&lt;/code&gt; related guest XML snippet
looks as follows (for a Fedora guest with Q35 machine type using an
OVMF build with SMM + SB enabled):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'x86_64'&lt;/span&gt; &lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pc-q35-3.0'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;hvm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt; &lt;span class="n"&gt;secure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pflash'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;edk2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ovmf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;OVMF_CODE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;secboot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;nvram&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/export/vmimages/fedora_VARS.secboot.fd'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libvirt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;qemu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nvram&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fedora_VARS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;secboot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;nvram&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'hd'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that Nova doesn’t need to worry about the NVRAM store from a
file management point of view because libvirt’s firmware
auto-selection feature also detects the NVRAM store associated
with the firmware image, copies it into the guest’s private path, and
asks the guest to use it.&lt;/p&gt;
&lt;p&gt;NB-1: The paths for the UEFI binary are different for different
distributions, but libvirt will handle that for us.&lt;/p&gt;
&lt;p&gt;NB-2: Q35 machine type is &lt;em&gt;mandatory&lt;/em&gt; for Secure Boot with OVMF.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For guests to truly get Secure Boot, we need to ensure that the
non-volatile store (“VARS”) file (in the above example,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fedora_VARS.secboot.fd&lt;/span&gt;&lt;/code&gt;) has the default UEFI keys enrolled.&lt;/p&gt;
&lt;p&gt;There are two ways to achieve that.  The first, use the “VARS”
template file (&lt;em&gt;with&lt;/em&gt; UEFI keys enrolled) that is shipped by your
Linux distribution; this is the preferred method.  The second, you
can enroll the default UEFI keys in the “VARS” file, using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;UefiShell.iso&lt;/span&gt;&lt;/code&gt; + &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EnrollDefaultKeys.efi&lt;/span&gt;&lt;/code&gt; utilities shipped by
various Linux distributions (as part of their EDK2 / OVMF packages),
and place it in the appropriate location.  There is a tool (refer
below) some Linux distributions ship which automates the key
enrollment process.  The tool is used as follows:&lt;/p&gt;
&lt;ol class="loweralpha"&gt;
&lt;li&gt;&lt;p&gt;Run the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ovmf-vars-generator&lt;/span&gt;&lt;/code&gt; tool (adjust the parameters
based on distibution) once:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&amp;gt; ./ovmf-vars-generator \
      --ovmf-binary /usr/share/edk2/ovmf/OVMF_CODE.secboot.fd \
      --uefi-shell-iso /usr/share/edk2/ovmf/UefiShell.iso \
      --ovmf-template-vars /usr/share/edk2/ovmf/OVMF_VARS.fd \
      --fedora-version 31 \
      --kernel-path /tmp/kernel \
      --kernel-url /path/to/vmlinuz \
      template_VARS.fd
...
INFO:root:Created and verified template_VARS.fd
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reboot the guest with a pointer to a unique copy of the above
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;template_VARS.fd&lt;/span&gt;&lt;/code&gt;.  At which point, you will &lt;em&gt;actually&lt;/em&gt; see
Secure Boot enabled. Which can be verified via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dmesg&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;(fedora-vm)$ dmesg | grep -i secure
[    0.000000] secureboot: Secure boot enabled
[    0.000000] Kernel is locked down from EFI secure boot; see man kernel_lockdown.7
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However, as noted earlier, no need to run the above steps manually.
Most common Linux distributions (SUSE, Fedora, RHEL) already ship a
“VARS” file with default UEFI keys enrolled.  Debian and Ubuntu also
ship them now &lt;a class="footnote-reference brackets" href="#id23" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If your distribution doesn’t ship a “VARS” file with default UEFI
keys enrolled, here &lt;a class="footnote-reference brackets" href="#id24" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;10&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; is a little Python tool,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ovmf-vars-generator&lt;/span&gt;&lt;/code&gt; that will automate the above three steps.
This is packaged in Fedora as a sub-RPM of EDK2/OVMF, called
‘edk2-qosb’.  Ubuntu has included this tool in its firmware package.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document the way to generate the above-mentioned “VARS” file using
the tool &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ovmf-vars-generator&lt;/span&gt;&lt;/code&gt;.  This tool is already shipped as a
sub-package (called: ‘edk2-qosb’) of the main ‘edk2’ / OVMF in
different distributions.  And Ubuntu and Debian are also working to
ship this script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a “trait” (needs update to ‘os-traits’ library) for Secure
Boot, so the image metadata can ask for the trait.  As noted earlier,
allows Nova to pick out only those hosts are Secure Boot-capable.
This requires ‘os-traits’ to be installed (or upgraded if need be) on
the host running &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;placement&lt;/span&gt;&lt;/code&gt; service.  Followed by a restart of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;placement&lt;/span&gt;&lt;/code&gt; service—this will synchronize the traits into the
Placement database.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For the SMM (System Management Mode) feature, only the QEMU Q35
machine type is supported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;=2.4 to get Secure Boot support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;=4.1.0 (released in August 2019) to get the firmware descriptor
files that conform to QEMU’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;firmware.json&lt;/span&gt;&lt;/code&gt; specification.  Here
&lt;a class="footnote-reference brackets" href="#id25" id="id11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;11&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; are some examples of the said “firmware descriptor files”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libvirt &amp;gt;=5.3 (released in May 2019) for the firmware auto-selection
feature and the ability to query the availability of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;efi&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id26" id="id12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;12&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
firmware via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;getDomainCapabilities()&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OVMF &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;0~20190606.20d2e5a1-2ubuntu1&lt;/span&gt;&lt;/code&gt; in Ubuntu (Eoan) release, to
provide the JSON descriptor files &lt;a class="footnote-reference brackets" href="#id27" id="id13" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;13&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This feature should be possible (assuming the earlier-mentioned
minimum libvirt and QEMU versions are available) to test in the upstream
gating environment.  Where the Nova instance should be able to boot a
KVM guest with Secure Boot (using OVMF), and verify in &lt;cite&gt;dmesg&lt;/cite&gt; that
Secure Boot is &lt;em&gt;actually&lt;/em&gt; in effect.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Document how to boot &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x86_64&lt;/span&gt;&lt;/code&gt; Nova instances with Secure Boot for QEMU
and KVM guests using OVMF.  And update Glance’s “Useful image
properties” documentation &lt;a class="footnote-reference brackets" href="#id28" id="id14" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;14&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;The blueprint that added initial support for booting from a UEFI
image:
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/boot-from-uefi.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/boot-from-uefi.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/ocata/implemented/hyper-v-uefi-secureboot.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/ocata/implemented/hyper-v-uefi-secureboot.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id17" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.ubuntu.com/UEFI/SecureBoot/Testing"&gt;https://wiki.ubuntu.com/UEFI/SecureBoot/Testing&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id18" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;The OVMF whitepaper:
&lt;a class="reference external" href="http://www.linux-kvm.org/downloads/lersek/ovmf-whitepaper-c770f8c.txt"&gt;http://www.linux-kvm.org/downloads/lersek/ovmf-whitepaper-c770f8c.txt&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id19" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;An overview of Secure Boot:
&lt;a class="reference external" href="http://www.rodsbooks.com/efi-bootloaders/secureboot.html"&gt;http://www.rodsbooks.com/efi-bootloaders/secureboot.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id20" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;The libvirt feature that allows auto-selection of firmware:
&lt;a class="reference external" href="https://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=1dd24167b"&gt;https://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=1dd24167b&lt;/a&gt;
(“news: Document firmware autoselection for QEMU driver”)&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id21" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;QEMU’s firmware schema file that describes the different uses
and properties of virtual machine firmware:
&lt;a class="reference external" href="https://git.qemu.org/?p=qemu.git;a=blob;f=docs/interop/firmware.json"&gt;https://git.qemu.org/?p=qemu.git;a=blob;f=docs/interop/firmware.json&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id22" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/isolate-aggregates.html"&gt;https://docs.openstack.org/nova/latest/reference/isolate-aggregates.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id23" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Refer to the first point:
“debian/patches/enroll-default-keys.patch: Build
EnrollDefaultKeys.efi to provide an automated way of injecting
Microsoft signing keys in VMs that need them.” –
&lt;a class="reference external" href="https://launchpad.net/ubuntu/+source/edk2/0~20190309.89910a39-1ubuntu1"&gt;https://launchpad.net/ubuntu/+source/edk2/0~20190309.89910a39-1ubuntu1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id24" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;10&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;A tool to generate OVMF variables file with default Secure Boot keys
enrolled – &lt;a class="reference external" href="https://github.com/puiterwijk/qemu-ovmf-secureboot/"&gt;https://github.com/puiterwijk/qemu-ovmf-secureboot/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id25" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id11"&gt;11&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;The EDK2 firmware descriptor files are located here:
&lt;a class="reference external" href="https://git.qemu.org/?p=qemu.git;a=tree;f=pc-bios/descriptors"&gt;https://git.qemu.org/?p=qemu.git;a=tree;f=pc-bios/descriptors&lt;/a&gt;.
E.g. the descriptor for “UEFI firmware for x86_64, with Secure
Boot and SMM”:
&lt;a class="reference external" href="https://git.qemu.org/?p=qemu.git;a=blob;f=pc-bios/descriptors/50-edk2-x86_64-secure.json"&gt;https://git.qemu.org/?p=qemu.git;a=blob;f=pc-bios/descriptors/50-edk2-x86_64-secure.json&lt;/a&gt;;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id26" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id12"&gt;12&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;The BIOS-related libvirt guest XML attributes:
&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsOSBIOS"&gt;https://libvirt.org/formatdomain.html#elementsOSBIOS&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id27" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id13"&gt;13&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/edk2/+bug/1836859"&gt;https://bugs.launchpad.net/ubuntu/+source/edk2/+bug/1836859&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id28" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id14"&gt;14&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/glance/rocky/admin/useful-image-properties.html"&gt;https://docs.openstack.org/glance/rocky/admin/useful-image-properties.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id29"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>libvirt - Store and allow the default machine type to be changed</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/libvirt-default-machine-type.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-default-machine-type"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-default-machine-type&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;QEMU’s “machine type” concept can be thought of a virtual chipset that
provides certain default devices (e.g. PCIe graphics card, Ethernet
controller, SATA controllae, etc).  QEMU supports two main variants of
“machine type” for x86 hosts: (a) &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc&lt;/span&gt;&lt;/code&gt;, which corresponds to Intel’s
I440FX chipset, which is twenty-two years old as of this writing; and
(b) &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt;, which corresponds to Intel’s 82Q35 chipset (released in
2007; a relatively modern chipset).  For AArch64 hosts, the machine type
is called: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc&lt;/span&gt;&lt;/code&gt; machine type is considered “legacy”, and does not support some of
the modern features.  Although at this time of writing, upstream QEMU has not
reached an agreement to remove new versioned variants of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc&lt;/span&gt;&lt;/code&gt; machine
type, some long-term stable Linux distributions (CentOS, RHEL, possibly others)
are moving to support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; only.&lt;/p&gt;
&lt;p&gt;The libvirt virt driver has long supported the configuration of a per compute
host &lt;a class="reference external" href="https://review.opendev.org/#/c/100664/"&gt;default machine type&lt;/a&gt; via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]/hw_machine_type&lt;/span&gt;&lt;/code&gt; configurable
for use by QEMU and KVM based instances. This configurable provides a default
machine type per host architecture to be used when no corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt; image property is provided for the instance.&lt;/p&gt;
&lt;p&gt;When the configurable is not defined the libvirt driver relies on the following
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/dc93e3b510f53d5b2198c8edd22528f0c899617e/nova/virt/libvirt/utils.py#L631-L638"&gt;hardcoded dictionary&lt;/a&gt; of default machine types per architecture:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;default_mtypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;obj_fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ARMV7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"virt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;obj_fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AARCH64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"virt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;obj_fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S390&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"s390-ccw-virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;obj_fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S390X&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"s390-ccw-virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;obj_fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I686&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;obj_fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X86_64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;However the resulting machine type used by the instance is not recorded by
Nova. As such the configurable (if set) and hardcoded defaults within the
libvirt driver must remain consistent between hosts in an environment &lt;em&gt;and&lt;/em&gt; can
never be changed without changing the emulated hardware exposed to the guest,
breaking the application binary interface (ABI) of the instances after hard
reboot, move or re-creation operations.&lt;/p&gt;
&lt;p&gt;This spec aims to outline how we can avoid this by always storing the machine
type for the lifetime of the instance. This will allow both operators and
developers to make changes to the default machine type over time while not
breaking existing instances.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a developer working on the libvirt driver I would like to update the
default machine type for a given host architecture to make use of newer
models of emulated hardware and features of QEMU.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator of an existing OpenStack environment I want to default to a
new machine type while not breaking the ABI of existing instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to ensure the ABI of my instance remains the same throughout
the lifetime of the instance, regardless of default configurable changes made
by an operator or virt driver developers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Store the used machine type in the instance system metadata table during the
initial spawn of the instance &lt;em&gt;or&lt;/em&gt; init_host of the compute service for all
running instances that don’t have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt; already stored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the stored machine type is used during a hard reboot, move or any
other action that results in the domain being redefined aside from a full
rebuild of the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unset the stored machine type during a rebuild allowing a new image defined
machine type or host configured default to be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow operators to get the machine type of instances via a new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_machine_type&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow operators to set or update the machine type of instances with a
vm_state of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED_OFFLOADED&lt;/span&gt;&lt;/code&gt; via a new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_machine_type&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The machine type will be stored within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; object under the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; field that is a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DictOfNullableStringsField&lt;/span&gt;&lt;/code&gt; using the
key &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will now be able to change the default machine type for a given
architecture without changing the underlying ABI presented to existing
instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Libvirt driver developers will now be able to change the default machine type
without changing the underlying ABI presented to existing instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;When upgrading to Wallaby from Victoria (or earlier) on startup the libvirt
driver will attempt to record the current machine type of each non-deleted
instance residing on the host. This includes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PAUSED&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED&lt;/span&gt;&lt;/code&gt; instances.  Where possible this will come from a direct query of
the underlying guest domain but if one is not found it will instead come from
the instance image metadata property &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]/hw_machine_type&lt;/span&gt;&lt;/code&gt; configurable or legacy hardcoded defaults.&lt;/p&gt;
&lt;p&gt;For non-deleted instances that are marked as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED_OFFLOADED&lt;/span&gt;&lt;/code&gt; and thus
don’t reside on a compute host a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_machine_type&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;
command will be introduced that will allow operators to set a machine
type. As above this will rely first on any stored image properties but if none
is found will require a specific machine type to be provided by the caller.&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; command will be introduced to allow operators to
determine when all non-deleted instances have had a machine type recorded
across an environment.&lt;/p&gt;
&lt;p&gt;While the aliased machine types (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; for example) will be documented as the
recommended choice admins and operators will be allowed to configure a
versioned machine either per image or per architecture on a given compute host.&lt;/p&gt;
&lt;p&gt;As a result the same &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_machine_type&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command used to
set the machine type of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED_OFFLOADED&lt;/span&gt;&lt;/code&gt; instances will also be able to
update the machine type of instances with a vm_state of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED_OFFLOADED&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This will allow operators to migrate instances between these versioned machine
types overtime without a full rebuild of the instance.&lt;/p&gt;
&lt;p&gt;It should be noted that by default this command will not allow the machine_type
to be changed between actual types of machine_type, for example &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pc&lt;/span&gt;&lt;/code&gt; to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; or between a newer and older version of a machine type.&lt;/p&gt;
&lt;p&gt;By default both will continue to require a full rebuild of the instance using a
new image with associated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt; image property set or once the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]/hw_machine_type&lt;/span&gt;&lt;/code&gt; defaults have been updated on the launching
compute host.&lt;/p&gt;
&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--force&lt;/span&gt;&lt;/code&gt; flag will be inlcuded to allow operators to force through
changes in both cases with a warning that the operation will likely break the
ABI within the instance once restarted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Store the used machine type in the instance extras table during the initial
spawn of the instance &lt;em&gt;or&lt;/em&gt; init_host of the compute service for all running
instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the stored machine type is used during a hard reboot, move or any
other action that results in the domain being redefined aside from a full
rebuild of the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unset the stored machine type during a rebuild allowing a new image defined
machine type or host configured default to be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_machine_type&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command to allow operators
to get the recorded machine_type of an instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_machine_type&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; command to allow
operators to set or update the recorded machine_type for a given instance
with a vm_state of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVED_OFFLOADED&lt;/span&gt;&lt;/code&gt; allowing
upgrades between versioned machine types over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt;&lt;/code&gt; upgrade check to ensure the machine_type has
been updated for all instances residing on a given host in the env or across
all hosts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write extensive operator documentation for the above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;grenade&lt;/span&gt;&lt;/code&gt; job will be extended to ensure the machine_type field is
being populated during compute service startup when using the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Extensive operator documentation covering the upgrade impact and use of the
configurable will be written.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Add IP address to libvirt guest metadata</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/libvirt-driver-ip-metadata.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-driver-ip-metadata"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-driver-ip-metadata&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Past Blueprint &lt;a class="footnote-reference brackets" href="#id4" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; has provided useful instance information to system
administrators through the libvirt domain XML configuration. This time,
I propose to extend this metadata to include IP addresses of instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In a virtualized environment using libvirt, qemu and kvm, the instance
configuration information is stored in XML and used by libvirt to launch
and manage instances.&lt;/p&gt;
&lt;p&gt;This XML contains useful configuration information such as instance names,
flavors and images as metadata &lt;a class="footnote-reference brackets" href="#id5" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Here, I noticed that IP addresses are
not included.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;With this proposal, we can get IP addresses of instances on the nova-compute
node without going through nova or neutron’s REST API. As an example, operators
can collect and monitor statistics based on an instance’s IP address at the low
cost of simply loading XML. In addition, from the vendor’s point of view,
the IP addresses of the instances can be easily obtained. This will reduce
unnecessary communication between users and vendors.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;So I propose to add IP addresses to the metadata in this Blueprint.
Here is an example of the metadata description with the IP address.
If an instance has more than one IP address, enumerate those IP addresses.&lt;/p&gt;
&lt;p&gt;The port attach or detach is performed dynamically after the creation of the
instance. Every time there is a change, it is reflected in the contents of
the XML.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&amp;lt;domain type='kvm' id='5'&amp;gt;
  ...
  &amp;lt;metadata&amp;gt;
    &amp;lt;nova:instance xmlns:nova="http://openstack.org/xmlns/libvirt/nova/1.0"&amp;gt;
      &amp;lt;nova:package version="18.1.1"/&amp;gt;
      &amp;lt;nova:name&amp;gt;sample-instance-name&amp;lt;/nova:name&amp;gt;
      &amp;lt;nova:creationTime&amp;gt;2020-10-23 05:36:41&amp;lt;/nova:creationTime&amp;gt;
      &amp;lt;nova:flavor name="sample-flavor"&amp;gt;
        &amp;lt;nova:memory&amp;gt;348160&amp;lt;/nova:memory&amp;gt;
        &amp;lt;nova:disk&amp;gt;100&amp;lt;/nova:disk&amp;gt;
        &amp;lt;nova:swap&amp;gt;0&amp;lt;/nova:swap&amp;gt;
        &amp;lt;nova:ephemeral&amp;gt;0&amp;lt;/nova:ephemeral&amp;gt;
        &amp;lt;nova:vcpus&amp;gt;80&amp;lt;/nova:vcpus&amp;gt;
      &amp;lt;/nova:flavor&amp;gt;
      &amp;lt;nova:owner&amp;gt;
        &amp;lt;nova:user uuid="2997526f-669c-4bd9-af5f-68c6ba0cc2f0"&amp;gt;sample-user&amp;lt;/nova:user&amp;gt;
        &amp;lt;nova:project uuid="acf923f2-9b4d-4e0d-acfb-1b2976dd480f"&amp;gt;sample-project&amp;lt;/nova:project&amp;gt;
      &amp;lt;/nova:owner&amp;gt;
      &amp;lt;nova:root type="image" uuid="66e81ebe-9d4f-45ae-b79b-b3d9dc989b21"/&amp;gt;

      &amp;lt;!-- I suggest adding following lines --&amp;gt;
      &amp;lt;nova:ports&amp;gt;
        &amp;lt;nova:port uuid="567a4527-b0e4-4d0a-bcc2-71fda37897f7"&amp;gt;
          &amp;lt;nova:ip type="fixed" address="192.168.1.1" ipVersion="4"/&amp;gt;
          &amp;lt;nova:ip type="fixed" address="fe80::f95c:b030:7094" ipVersion="6"/&amp;gt;
          &amp;lt;nova:ip type="floating" address="11.22.33.44" ipVersion="4"/&amp;gt;
        &amp;lt;/nova:port&amp;gt;
        &amp;lt;nova:port uuid="a3ca97e2-0cf9-4159-9bfc-afd55bc13ead"&amp;gt;
          &amp;lt;nova:ip type="fixed" address="10.0.0.1" ipVersion="4"/&amp;gt;
          &amp;lt;nova:ip type="fixed" address="fdf8:f53b:82e4::52" ipVersion="6"/&amp;gt;
          &amp;lt;nova:ip type="floating" address="1.2.3.4" ipVersion="4"/&amp;gt;
        &amp;lt;/nova:port&amp;gt;
      &amp;lt;/nova:ports&amp;gt;

    &amp;lt;/nova:instance&amp;gt;
  &amp;lt;/metadata&amp;gt;
  ...
&amp;lt;/domain&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Of course, we can get IP addresses of instances via the REST API.
However, in the above use case, we can get that information at a lower
cost by loading XML.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None. Existing metadata is not manipulated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nmiki&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Liaison Needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new object that corresponds to the IP address in
nova/virt/libvirt/config.py. For example, it would be named something
like LibvirtConfigGuestMetaNovaIp.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add network_info as an argument to _get_guest_config_meta to retrieve
information about networks, including IP addresses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add set_metadata method to Guest class in nova/virt/libvirt/guest.py.
By calling libvirt’s virDomainSetMetadata API &lt;a class="footnote-reference brackets" href="#id6" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; , it updates the metadata
in the XML in real time when the port attaches and detaches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In nova/virt/libvirt/driver.py, call guest.set_metadata in the
attach_interface and detach_interface methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement unit tests in nova/tests/unit/virt/libvirt/test_config.py.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;There is no integration with other systems, so only unit tests can ensure
correctness. It covers the case of having no IP address, only one, or
multiple IP addresses. This feature is mainly intended for debugging purposes
for developers and administrators. It is not an official external interface.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Documentation for administrators describing that IP addresses are added
as metadata in libvirt xml.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-driver-domain-metadata"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-driver-domain-metadata&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsMetadata"&gt;https://libvirt.org/formatdomain.html#elementsMetadata&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainSetMetadata"&gt;https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainSetMetadata&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Remove resource information from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-hypervisors&lt;/span&gt;&lt;/code&gt; API</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/modernize-os-hypervisors-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/modernize-os-hypervisors-api"&gt;https://blueprints.launchpad.net/nova/+spec/modernize-os-hypervisors-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-hypervisors&lt;/span&gt;&lt;/code&gt; API is around since the early days of nova. Back in
those halcyon days, it provided a nice way to get a quick summary of the
resource usage of individual compute nodes in your deployment. Today, however,
it’s a shell of itself. The more detailed information it returns is
hypervisor-specific and frequently wrong, especially with advanced features
like CPU pinning or file-based memory. With the elevation of placement to its
rightful place as lord of (almost) all things resource’y, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-hypervisor&lt;/span&gt;&lt;/code&gt;
API needs to slim down significantly.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The majority of this spec is focused on changes to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/detail&lt;/span&gt;&lt;/code&gt; API. Consider the output of a typical &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;
&lt;span class="pre"&gt;/os-hypervisors/detail&lt;/span&gt;&lt;/code&gt; call, as taken from the API ref &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"hypervisors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"cpu_info"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"arch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"x86_64"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nehalem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"vendor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Intel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s2"&gt;"pge"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="s2"&gt;"clflush"&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"topology"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nt"&gt;"cores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nt"&gt;"threads"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nt"&gt;"sockets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"current_workload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"disk_available_least"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"host_ip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.1.1.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"free_disk_gb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1028&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"free_ram_mb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7680&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"hypervisor_hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"host1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"hypervisor_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fake"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"hypervisor_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"local_gb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1028&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"local_gb_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"memory_mb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"memory_mb_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"running_vms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"host1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"disabled_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"vcpus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"vcpus_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"hypervisors_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/os-hypervisors/detail?limit=1&amp;amp;marker=2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The fields here broadly fall into three categories: useful but duplicated in
the summary (non-detailed) view, useful and unique to the detailed view, and
not useful. First, the useful but duplicated fields. These should remain:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next, the useful fields unique to the detailed view. These should also remain:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host_ip&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_type&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_version&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, the useless fields. There are varied reasons their uselessness,
described below, but all should be removed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;current_workload&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This tracks “the number of tasks the hypervisor is responsible for” and it
“will be equal or greater than the number of active VMs on the system (it can
be greater when VMs are being deleted and the hypervisor is still cleaning
up)” &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This information is easily calculated by listing active and
deleted instances.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Useful at face value but the only thing relevant for scheduling purposes are
the CPU architecture and CPU features, all of which are already handled by
placement trait requests. The topology field is an oddity that should likely
never have been added. It’s not usable in scheduling and is possibly wrong,
given it doesn’t reflect offline CPUs or those not available to nova due to
configuration, and it doesn’t handle non-uniform CPU topologies where there
are e.g. more cores on one socket than another. If the operator wants this
information, they can simply inspect the host like they would have to do to
identify e.g. the specifics of PCI devices or storage devices.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;free_disk_gb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local_gb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local_gb_used&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;💩 Almost always wrong if shared storage is in use and doesn’t take
overcommit into account. Use placement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_available_least&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Reflects the estimated available disk space on the hypervisor if all
instances on the host were to use all their allocated disk. This can go
negative if disk overcommit is enabled or if an instance is force migrated to
a host, bypassing the scheduler. This value is hard to use and frequently
misunderstood by end-users.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;free_ram_mb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memory_mb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memory_mb_used&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Doesn’t take overcommit or non-default pagesizes into account. Use placement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpus&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpus_used&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Doesn’t take overcommit or PCPU inventory into account. Use placement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;running_vms&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Easily figured out by filtering running instances by host (admin-only, like
this API).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition to the changes to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/detail&lt;/span&gt;&lt;/code&gt; API, there are
also two other APIs that appear to have outlived their usefulness:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/statistics&lt;/span&gt;&lt;/code&gt;, which provides summary information of the
above, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/{hypervisor_id}/uptime&lt;/span&gt;&lt;/code&gt;, which provides an entire
API to a single figure. The former can be removed entirely in favour of
placement, while the latter can be replaced by a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uptime&lt;/span&gt;&lt;/code&gt; field on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/{hypervisor_id}&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=list-hypervisors-details-detail,show-hypervisor-details-detail"&gt;https://docs.openstack.org/api-ref/compute/?expanded=list-hypervisors-details-detail,show-hypervisor-details-detail&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=list-hypervisors-details-detail#id298"&gt;https://docs.openstack.org/api-ref/compute/?expanded=list-hypervisors-details-detail#id298&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I don’t want to see misleading information reported from my API.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Remove the resource-related fields from the output of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/detail&lt;/span&gt;&lt;/code&gt; API and remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/statistics&lt;/span&gt;&lt;/code&gt;
API in its entirety.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could document the incorrect nature of these APIs. This is less desirable
since people don’t read documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Starting from the new API microversion, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/detail&lt;/span&gt;&lt;/code&gt; API will
no longer include the following fields in its response: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;free_disk_gb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local_gb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local_gb_used&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_available_least&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;free_ram_mb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memory_mb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memory_mb_used&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpus&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpus_used&lt;/span&gt;&lt;/code&gt;,
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;running_vms&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/statistics&lt;/span&gt;&lt;/code&gt; API contains summary information of the
above fields and will be removed entirely, returning a HTTP 404 (Not Found) on
the new API microversion.&lt;/p&gt;
&lt;p&gt;The uptime information shown by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/{hypervisor_id}/uptime&lt;/span&gt;&lt;/code&gt;
API doesn’t warrant its own API and will also return a HTTP 404 (Not Found) on
the new API microversion. This information will be accessible via a new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uptime&lt;/span&gt;&lt;/code&gt; field on responses from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/{hypervisor_id}&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The clients will need to be updated. Documentation referencing these APIs will
need to be updated with recommendations to look at placement or other APIs
instead. Regarding the changes to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/detail&lt;/span&gt;&lt;/code&gt; API:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;free_disk_gb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local_gb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;local_gb_used&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;free_ram_mb&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memory_mb&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;memory_mb_used&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpus&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpus_used&lt;/span&gt;&lt;/code&gt; values can be
identified using a combination of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;resource&lt;/span&gt; &lt;span class="pre"&gt;provider&lt;/span&gt; &lt;span class="pre"&gt;inventory&lt;/span&gt;
&lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;resource&lt;/span&gt; &lt;span class="pre"&gt;provider&lt;/span&gt; &lt;span class="pre"&gt;usage&lt;/span&gt; &lt;span class="pre"&gt;show&lt;/span&gt;&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack hypervisor show devstack-1 \
    -c local_gb -c local_gb_used -c free_disk_gb \
    -c memory_mb -c memory_mb_used -c free_ram_mb \
    -c vcpus -c vcpus_used
+----------------+-------+
| Field          | Value |
+----------------+-------+
| local_gb       | 18    |
| local_gb_used  | 1     |
| free_disk_gb   | 19    |
| memory_mb      | 16035 |
| memory_mb_used | 1024  |
| free_ram_mb    | 15011 |
| vcpus          | 12    |
| vcpus_used     | 1     |
+----------------+-------+

$ openstack resource provider inventory list bde27f9d-1249-446f-ae14-45f6ff3e63d5
+----------------+------------------+----------+----------+----------+-----------+-------+
| resource_class | allocation_ratio | min_unit | max_unit | reserved | step_size | total |
+----------------+------------------+----------+----------+----------+-----------+-------+
| VCPU           |             16.0 |        1 |       12 |        0 |         1 |    12 |
| MEMORY_MB      |              1.5 |        1 |    16035 |      512 |         1 | 16035 |
| DISK_GB        |              1.0 |        1 |       19 |        0 |         1 |    19 |
+----------------+------------------+----------+----------+----------+-----------+-------+

$ openstack resource provider usage show bde27f9d-1249-446f-ae14-45f6ff3e63d5
+----------------+-------+
| resource_class | usage |
+----------------+-------+
| VCPU           |     1 |
| MEMORY_MB      |   512 |
| DISK_GB        |     1 |
+----------------+-------
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;running_vms&lt;/span&gt;&lt;/code&gt; value can be identified using by filter instances by host
using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt; &lt;span class="pre"&gt;--host&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;HOST&amp;gt;&lt;/span&gt;&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack hypervisor show devstack-1 -c running_vms
+-------------+-------+
| Field       | Value |
+-------------+-------+
| running_vms | 1     |
+-------------+-------+

$ openstack server list --host devstack-1 -c ID -f yaml | wc -l
1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is not a 1:1 replacement since the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;running_vms&lt;/span&gt;&lt;/code&gt; setting will track
all VMs running on the hypervisor, including those not managed by nova.
However, having VMs not managed by nova on a hypervisor is considered a
misconfiguration and is irrelevant for scheduling purposes.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info.arch&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info.features&lt;/span&gt;&lt;/code&gt; values are published as
traits and can be inspected using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;resource&lt;/span&gt; &lt;span class="pre"&gt;provider&lt;/span&gt; &lt;span class="pre"&gt;trait&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt;.
For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack hypervisor show devstack-1 -f yaml -c cpu_info
cpu_info: '{"arch": "x86_64", "model": "IvyBridge-IBRS", "vendor": "Intel", "topology":
  {"cells": 2, "sockets": 1, "cores": 3, "threads": 2}, "features": ["xsaveopt", "erms",
  "ssbd", "arch-capabilities", "nx", "cx16", "ht", "mca", "tsc-deadline", "amd-ssbd",
  "pcid", "pse", "ss", "syscall", "md-clear", "tsc_adjust", "mmx", "rdtscp", "f16c",
  "fxsr", "lahf_lm", "spec-ctrl", "smep", "pse36", "vme", "de", "sse", "xsave", "clflush",
  "cmov", "msr", "pat", "aes", "hypervisor", "mtrr", "sep", "fsgsbase", "tsc", "sse2",
  "apic", "pdpe1gb", "cx8", "umip", "vmx", "pae", "skip-l1dfl-vmentry", "popcnt",
  "ssse3", "avx", "pclmuldq", "x2apic", "lm", "stibp", "fpu", "ibpb", "rdrand", "sse4.1",
  "pni", "pge", "sse4.2", "pschange-mc-no", "mce", "arat"]}'

$ openstack --os-placement-api-version 1.8 \
    resource provider trait list bde27f9d-1249-446f-ae14-45f6ff3e63d5 | grep CPU
| HW_CPU_X86_AMD_SVM                    |
| HW_CPU_X86_SSE2                       |
| HW_CPU_X86_SSE                        |
| HW_CPU_X86_SVM                        |
| HW_CPU_HYPERTHREADING                 |
| HW_CPU_X86_MMX                        |
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_available_least&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info.model&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info.vendor&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info.topology&lt;/span&gt;&lt;/code&gt; values are not relevant for scheduling and therefore
have no direct replacement in placement or another API. They can, however, be
identified through inspection of the host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Horizon will need to be updated to talk to placement or use this API with an
older microversion. Similarly, any users of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/{hypervisor_id}/uptime&lt;/span&gt;&lt;/code&gt; API will need to use the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-hypervisors/{hypervisor_id}&lt;/span&gt;&lt;/code&gt; API instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the APIs in a new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation to remove references to these deprecated APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the clients to reflect the deprecations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional tests. Tempest tests will need to be updated to cap against
the latest microversion to support these APIs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;References to the APIs will need to be removed or updated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated to remove references to policy changes, which were deferred.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Port Scoped SR-IOV NUMA Affinity Policies</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/port-scoped-sriov-numa-affinity.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/port-scoped-sriov-numa-affinity"&gt;https://blueprints.launchpad.net/nova/+spec/port-scoped-sriov-numa-affinity&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the Ussuri release &lt;a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; support was added to allow PCI NUMA affinity
policies to be specified via flavor or image. This work builds on a previous
feature introduced in the Ussuri release and extends the granularity to allow
per neutron port NUMA affinity policies.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In some environments the server form factor is restricted, preventing PCI
devices from being physically installed across all NUMA nodes on a server,
e.g. high density blade/multi server systems or non standard form factor
equipment. In the Ussuri release operators gained the flexibility to specify
a VM-wide NUMA affinity policy via the flavor or image however in many cases
different NICs have different constraint.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator deploying openstack on high density or restricted form factor
hardware, I wish to specify a per-port NUMA affinity policy for SR-IOV devices
that differs form the VM-wide pci NUMA affinity policy.&lt;/p&gt;
&lt;p&gt;As a tenant or VNF vendor, I want to be able to customize the affinity of
network interfaces, based on their usage. i.e. strict affinity for dataplane
interfaces and no affinity for management interfaces.&lt;/p&gt;
&lt;p&gt;As an operator I wish to utilize NUMA-aware vSwitches but still be able to
disable it for individual VM interfaces.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Per interface NUMA affinity polices have been introduced via a neutron
API extension &lt;a class="footnote-reference brackets" href="#id9" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. The neutron API extension introduces a new port attribute
which holds the requested affinity policy. Port NUMA affinity policies will
have a higher precedence than flavor,image or config based policy
specifications. As a result the precedence relationship will be
port &amp;gt; image/flavor &amp;gt; PCI alias.&lt;/p&gt;
&lt;p&gt;This will enable operators to specify a default affinity policy per PCI alias,
this in turn can be overriden per VM via the flavor and image and finally the
NIC affinity can be refined via the per port policy.&lt;/p&gt;
&lt;p&gt;The flavor- and image-based approach covers 80% of the use cases
enabled by per-interface NUMA affinity polices without requiring neutron API
changes. Now that the neutron API has been enhanced to support port NUMA
affinity policies this spec can address the final 20% of usecases.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec will address NUMA affinity for NUMA instance only. If a VM would
not otherwise have a NUMA topology, a per port NUMA affinity policy will
not make the instance a NUMA instance. This feature will support both SR-IOV
NUMA affinity and NUMA aware vswitches but will not apply to cyborg managed
interfaces.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To assist with scheduling a new compute capability trait
COMPUTE_NET_NUMA_AFFINITY will be added. The libvirt driver will be modified
to report this trait if it is configured with either SR-IOV network interfaces
via the PCI passthough whitelist or NUMA aware vswitches.&lt;/p&gt;
&lt;p&gt;A prefilter will be added to append a required traits request to the unnamed
traits group when a port NUMA affinity policy is present. This is required
to the required the strict affinity policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;require&lt;/span&gt;&lt;/code&gt; for NUMA deployments
that use NUMA aware vswitches.&lt;/p&gt;
&lt;p&gt;The neutron api extension &lt;a class="footnote-reference brackets" href="#id9" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; will be update to support the newly added
socket pci affinity policy [3].&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.network.model.VIF&lt;/span&gt;&lt;/code&gt; object will be extended with a NUMA affinity
policy. While this is stored in the database, it is stored as a json blob
in the network info cache so it will not alter the schema or rpc objects.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no direct changes to any existing API in Nova. However,
a new API extension &lt;a class="footnote-reference brackets" href="#id9" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; has been added to neutron to store the port
NUMA affinity policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;As the scheduler already supports PCI affinity adding a new way to
pass the PCI policy should have no effect on scheduling performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As was previously required to enable NUMA affinity to be enforced for
SR-IOV/PCI devices, the PCI pass-through and NUMA topology filters must be
enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The socket NUMA affinity policy depends on &lt;a class="footnote-reference brackets" href="#id10" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.
The only other dependency is on extending the request spec
object to store the requested networks. This is part
of the routed networks spec &lt;a class="footnote-reference brackets" href="#id11" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; implemented by &lt;a class="footnote-reference brackets" href="#id12" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;As this feature relates to SR-IOV it cannot be tested in the upstream gate
via tempest. Unit tests will be provided to assert that the policy
is correctly conveyed to the existing PCI assignment code and the existing
functional test can be extended as required. As this feature simply provides
another way to specify the PCI affinity policy the code change is minimal and
can leverage much of the existing test coverage. The most important thing to
assert is the precedence relationship of polices between config, flavor, image
and port.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A release note and updates to the networking docs will be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/vm-scoped-sriov-numa-affinity.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/vm-scoped-sriov-numa-affinity.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/neutron-specs/specs/victoria/port-numa-affinity-policy.html"&gt;https://specs.openstack.org/openstack/neutron-specs/specs/victoria/port-numa-affinity-policy.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/pci-socket-policy.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/pci-socket-policy.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/routed-networks-scheduling.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/routed-networks-scheduling.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/749977"&gt;https://review.opendev.org/c/openstack/nova/+/749977&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id13"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Scheduling support for Routed Networks</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/routed-networks-scheduling.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/routed-networks-scheduling"&gt;https://blueprints.launchpad.net/nova/+spec/routed-networks-scheduling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Neutron provides network segments support thanks to Routed Networks where you
can create a port allocated to a specific segment. Unfortunately, Nova doesn’t
verify the segment at every instance operation, including those where you move
an instance, which leads to inconsistencies.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Although it’s possible to create a Neutron port with a routed networks setup
and boot an instance with this port, the network locality of the compute node
associated with the instance won’t be verified by the scheduler and could
lead to a wrong scheduling decision. This is problematic when a move operation
sends an instance to a compute node that isn’t in the network segment that is
related to the IP address that was allocated at boot time.&lt;/p&gt;
&lt;p&gt;As a result of this gap, the only way to use routed networks in Nova currently
is by creating a port having the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt; value be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deferred&lt;/span&gt;&lt;/code&gt; and
making sure that all compute services are assigned to at least one network
segment.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I’d like to make sure that instances IP addresses can be
correctly separated between the network segments I provided.&lt;/p&gt;
&lt;p&gt;As an operator, I don’t want to see instances going to compute services that
aren’t in network segments if the user asks for either a port or a routed
network.&lt;/p&gt;
&lt;p&gt;As a user, I’d like Nova to place my instance on the correct host  according to
the port or network I’ve requested for my instance, without having to
specifically create a port with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation=deferred&lt;/span&gt;&lt;/code&gt; value.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Once you &lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-routed-networks.html"&gt;configure routed networks in Neutron&lt;/a&gt;, network segments are
represented as Placement Resource Providers. Neutron will then ask Nova to
create a Nova host aggregate for each segment and will add compute services
that are mapped with respective segments into the related aggregates.
Eventually, Nova will mirror those aggregates into Placement aggregates.&lt;/p&gt;
&lt;p&gt;What we then need for Nova is to have a way for asking the Placement API to
only get resource providers (i.e. compute nodes) that are in the aggregate
related to the segments that are in the network passed by the user (or related
to the port that is asked).&lt;/p&gt;
&lt;p&gt;As Nova needs to find which segments are related and then which aggregates,
we could just provide a new pre-filter that would look at it if some
configuration option (say &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;query_placement_for_routed_network_aggregates&lt;/span&gt;&lt;/code&gt;)
would be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A pseudo-code for it would be :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;support_routed_networks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_spec&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_placement_for_routed_network_aggregates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
  &lt;span class="n"&gt;segment_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;get_all_segments_ids_from_network_or_port&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;segment&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;segment_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="n"&gt;agg_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;get_provider_aggregates_from_segment_id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;append_agg_info_to_required_aggregates&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As said below in the &lt;a class="reference internal" href="#alternatives"&gt;Alternatives&lt;/a&gt; section, we could have Neutron passing
directly the aggregates, so this pre-filter could be deprecated once we
do it.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of having a new pre-filter, we could provide a specific scheduler
filter. This said, given we limit the number of allocation candidates returned
by Placement, we could miss some good resource providers so the filter couldn’t
work.&lt;/p&gt;
&lt;p&gt;Another alternative would be to have Neutron passing directly the needed
aggregate to Nova instead of Nova asking Neutron for it, but that would mean
that we should modify Neutron to return the Placement needed query in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;port.resource_request&lt;/span&gt;&lt;/code&gt; attribute.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;We may need to augment the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; object to be able to provide in its
nested &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestLevelParams&lt;/span&gt;&lt;/code&gt; object attribute the specific aggregate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There could be a performance impact if we would verify the segments for every
instance in every cloud, but given we ask the operator to modify an option
if they want to use routed networks, we don’t really think this would be an
issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new configuration option would be:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoolOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"query_placement_for_routed_network_aggregates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bauzas&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;bauzas&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a new pre-filter that would find the related aggregate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the aggregate to the RequestSpec asking to verify it by Placement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That’s it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional tests of course, but Tempest tests would be nice as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Maybe modifying &lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-routed-networks.html"&gt;https://docs.openstack.org/neutron/latest/admin/config-routed-networks.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced, Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Support interface attach with QoS ports</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/support-interface-attach-with-qos-ports.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-interface-attach-with-qos-ports"&gt;https://blueprints.launchpad.net/nova/+spec/support-interface-attach-with-qos-ports&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-stein"&gt;microversion 2.72&lt;/a&gt; nova supports creating servers with neutron ports
having resource request. In the recent releases &lt;a class="reference external" href="https://docs.openstack.org/api-guide/compute/port_with_resource_request.html"&gt;support for the lifecycle
operations&lt;/a&gt; with such ports have also been added. The next step is to support
attaching QoS ports to running instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova does not support attaching ports to a running instance if the port has
resource request. Such &lt;a class="reference external" href="https://review.opendev.org/#/c/570078/"&gt;interface attach is rejected&lt;/a&gt; since Neutron added
support for port resource request in Stein.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an end user, I would like to add a new interface to my server that has QoS
minimum bandwidth rules and I want that such operation only succeeds if the
requested bandwidth can be guaranteed.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach_interface&lt;/span&gt;&lt;/code&gt; RPC handler in the ComputeManager needs to be extended
with the following logic:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Gather the port resource request from Neutron&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call placement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation_candidates&lt;/span&gt;&lt;/code&gt; API based on the port resource
request, but restrict the query with an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;in_tree&lt;/span&gt;&lt;/code&gt; filter to the current RP
tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the first candidate and note the resource provider mapping of the
candidate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the instance allocation based on the selected candidate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePciRequest&lt;/span&gt;&lt;/code&gt; of the port, if any, with the interface
name of the parent physical device based on the device resource provider the
port allocates from&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do the PCI claim, if any, as today&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the resource provider mapping to allocate_for_instance call candidate&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A couple of new error cases needs to be handled. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;attach_interface&lt;/span&gt;&lt;/code&gt;
compute RPC call is synchronous so the error cases could lead to HTTP error
codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Placement returns no allocation candidates then respond with  HTTP 400
similarly to NoValidHost&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updating the instance allocation fails due to resource conflict then retry
with another candidate. If we run out of candidates then respond with HTTP
400&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updating the instance allocation fails due to generation conflict then
reload allocations from placement and retry the update. If it still fails
after 3 retries then respond with HTTP 409&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updating the InstancePciRequest with parent interface name fails the respond
with HTTP 400&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the error cases keep the server in ACTIVE state and record a failed
instance action. Also none of these are introducing new HTTP response code for
this API so no new microversion is needed.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/os-interface&lt;/span&gt;&lt;/code&gt; with a Neutron port having resource
request will be accepted. This is a similar change to supporting move
operations with QoS ports and that was done without bumping a microversion. So
this change will also be made without a microversion bump.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;An extra placement allocation candidate query needs to be made to select which
physical device can accommodate the additional resource request on the host and
then the instance allocation needs to be updated in placement based on the
selected candidate. These queries will only be run if the port has resource
request and the allocation candidate query will be restricted to the host the
instance is currently running on so the overall performance impact is limited.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The main implementation of this feature will be in the ComputeManager in the
nova-compute service. So the compute service version needs to be bumped.
Currently, the API rejects such attach request. The related check in the API
needs to be replaced with a service level check to ensure that the attach is
only accepted if the compute service hosting the VM is new enough to support
the request.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;See them in the &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt; section&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional testing will be provided for both normal and PCI device
backed interfaces. Tempest tests will be provided for normal ports only due to
the CI system limitation regarding SRIOV capable network devices.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API guide &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/port_with_resource_request.html"&gt;Using ports with resource request&lt;/a&gt; will be updated accordingly.
Also the Limitations section of the neutron admin guide
&lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html"&gt;Quality of Service Guaranteed Minimum Bandwidth&lt;/a&gt; needs to be updated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 01 Apr 2021 00:00:00 </pubDate></item><item><title>Remove tenant_id</title><link>https://specs.openstack.org/openstack/nova-specs/specs/xena/approved/remove-tenant-id.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-tenant-id"&gt;https://blueprints.launchpad.net/nova/+spec/remove-tenant-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The blueprint proposes to remove the API interface that uses
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and replace it with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Nova API supports both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;,
which is unfriendly to users.&lt;/p&gt;
&lt;p&gt;The following is a confusing question.
By default, we support filtering instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt; &lt;span class="pre"&gt;(Optional)&lt;/span&gt;&lt;/code&gt;,
but through this parameter, we get a list of all instances that they
cannot get instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can see from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1185290"&gt;bug 1185290&lt;/a&gt; that when using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt; command,
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; is required, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; must appear, as description
in &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, which is somewhat unintuitive.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;a class="footnote-reference brackets" href="#id3" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; mainly said: “As explained in lp:#1185290, if &lt;cite&gt;all_tenants&lt;/cite&gt;
is not passed we must ignore the &lt;cite&gt;tenant_id&lt;/cite&gt; search option.”.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can know from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1468992"&gt;bug 1468992&lt;/a&gt; that many users want to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;
filtering instances, and using the concept of tenants in many of our
large-scale customer scenarios, they hope we can filter the expected
instances through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an (admin) user, I would like to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; uniformly in nova api,
instead of supporting both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;, this will imporve
uniformity within nova and between nova and other service which have already
made this change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to the request or response parameter changes API.&lt;/p&gt;
&lt;p&gt;Remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; field, using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt;
parameter, and then remove``all_tenants`` parameter in the following APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The keyword &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; in the path will be replaced with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; as below
APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage/{tenant_id}&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage/{project_id}&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We should block change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; below the deprecated APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups (List Security Groups)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups/{security_group_id} (Show Security Group Details)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-security-groups/{security_group_id} (Update Security Group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /os-security-group-rules (Create Security Group Rule)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-fping?all_tenants=1 (Ping Instances)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, tenant* reference will be replaced with project* in all policies,
code and docs too.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a new microversion.&lt;/p&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; parameter, and remove
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Update openstacksdk, python-novaclient and python-openstackclient
for the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the python-novaclient , python-openstackclient and openstacksdk,
just support requesting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in related APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test for negative scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test (API samples).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary for this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the API reference for the new microversion, and update all uses of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; in all docs and code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Mainly info: &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295"&gt;https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Xena&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 30 Mar 2021 00:00:00 </pubDate></item><item><title>Libvirt: support vDPA based networking</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/implemented/libvirt-vdpa-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-vdpa-support"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-vdpa-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Over the years a number of different technologies have been developed to
offload networking and other function to external processes in order to
accelerate QEMU instance performance. In kernel 5.7+ a new virtual bus know as
&lt;em&gt;vDPA&lt;/em&gt; (vHost data path acceleration) was introduced to provide a vendor
neutral way to accelerate standard virtio device using software or hardware
accelerator implementations. vDPA support was introduced in Libvirt 6.9.0 to
leverage the vDPA capabilities introduced in QEMU 5.1+.
This blueprint tracks enhancing nova to leverage these new capabilities
for offloading to hardware-based smart NICs via hardware offloaded OVS.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current hardware offloaded networking solutions require vendor specific drivers
in the guest to function. The vDPA bus allows an abstraction layer to exist
between the accelerator and the VM without the CPU overhead of traditional
software vHost implementations. vDPA-enabled vSwitch offloads allow
the guest to use standard virtio drivers instead of a vendor specific driver.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;While vDPA is expected to support live migration in the future, QEMU does
not currently support live migration with vDPA devices. One of the main
advantages of vDPA based networking over SR-IOV is the ability to abstract
the device state from the VM, allowing transparent live migration via a
software fallback. Until that fallback is implemented in QEMU, live
migration will be blocked at the API layer via a HTTP 409 (Conflict) error
response so that we can enable it without a new micro-version.&lt;/p&gt;
&lt;p&gt;As Open vSwitch is currently the only control plane capable of managing vDPA
devices, and since that requires hardware offloads to function, this spec
will focus on enabling vDPA networking exclusively with hardware-offloaded
OVS. In a future release this functionality can be extended to other vSwitch
implementations such as VPP or linux bridge if they become vDPA enabled.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to offer hardware-accelerated networking without
requiring tenants to install vendor-specific drivers in their guests.&lt;/p&gt;
&lt;p&gt;As an operator, I want to leverage hardware-accelerated networking while
maintaining the ability to have transparent live migration.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Transparent live migration will not initially be supported and will be
enabled only after it is supported officially in a future QEMU release.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new vnic-type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa&lt;/span&gt;&lt;/code&gt; has been introduced to neutron to request vDPA
offloaded networking. &lt;a class="reference external" href="https://github.com/openstack/neutron-lib/commit/8c6ab5e"&gt;https://github.com/openstack/neutron-lib/commit/8c6ab5e&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.network.model&lt;/span&gt;&lt;/code&gt; class will be extended to define the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa&lt;/span&gt;&lt;/code&gt;
vnic-type constant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The libvirt driver will be extended to generate the vDPA interface XML&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The PCI tracker will be extended with a new device-type, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VDPA&lt;/span&gt;&lt;/code&gt;.
While the existing whitelist mechanism is unchanged, if a device is
whitelisted and is bound to a vDPA driver, it will be inventoried as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VDPA&lt;/span&gt;&lt;/code&gt;. In the libvirt driver this will be done by extending the private
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_pci_passthrough_devices&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_device_type&lt;/span&gt;&lt;/code&gt; functions to detect
if a VF is a parent of a vDPA nodedev. These functions are called by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_available_resources&lt;/span&gt;&lt;/code&gt; in the resource tracker to generate the
resources dictionary consumed by  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_setup_pci_tracker&lt;/span&gt;&lt;/code&gt; at the startup of
the compute agent in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_init_compute_node&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The vDPA device type is required to ensure that the VF associated with vDPA
devices cannot be allocated to VMs via PCI alias or standard neutron SR-IOV
support. VFs associated with vDPA devices cannot be managed using standard
kernel control plane command such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip&lt;/span&gt;&lt;/code&gt;. As a result, allocating them
to an interface managed by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sriov-nic-agent&lt;/span&gt;&lt;/code&gt; or via alias-based PCI
passthrough is not valid. This will also provide automatic NUMA affinity
and a path to eventurally report vDPA devices in placement as part of
generic PCI device tracking in placement in the future.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could delegate vDPA support to cyborg.
This would still require the libvirt changes and neutron changes while
also complicating the deployment. Since vDPA-based NICs are fixed function
NICs there is not really any advantage to this approach that justifies
the added complexity of inter-service interaction.&lt;/p&gt;
&lt;p&gt;We could use the resources table added for vPMEM devices to track the devices
in the DB instead of the PCI tracker. This would complicate the code paths as
we would not be able to share any of the PCI NUMA affinity code that already
exists.&lt;/p&gt;
&lt;p&gt;We could support live migration by treating vDPA devices as if they are
direct mode SR-IOV interface, meaning nova would hot unplug and plug
the interface during the migration. In the future this could be replaced with
transparent live migration if the QEMU version on both hosts is new enough.
Since we don’t know when that will be, this option is deferred until a future
release to reduce complexity.&lt;/p&gt;
&lt;p&gt;A new workaround config option could be added
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_virtual_vdpa_devices=True|False&lt;/span&gt;&lt;/code&gt; (default: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;). When set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; it would allow a virtual vDPA devices such as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa_sim&lt;/span&gt;&lt;/code&gt;
devices to be tracked and used. Virtual PCI devices do not have a VF or PCI
device associated with them, so setting this value would result in the no-op
os-vif driver being used and a sentinel value being used to track the device
in the PCI tracker. This would allow testing without real vDPA hardware in CI
and is not intended for production use. This was declared out of scope to
avoid adding a config option and code that is purely used for testing.
Functional tests will be used instead to ensure adequate code coverage.&lt;/p&gt;
&lt;p&gt;A new standard trait &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NIC_VDPA&lt;/span&gt;&lt;/code&gt;  could be reported by the
libvirt driver on hosts with vDPA devices, and the required version of QEMU
and libvirt. This would be used in combination with a new placement prefilter
to append a required trait request to the unnamed group if any VM interface has
vnic-type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa&lt;/span&gt;&lt;/code&gt;. This will not be done as it will not be required when
PCI devices are tracked in placement. Since standard traits cannot be removed,
no new trait will be added and the PCI passthrough filter will instead be used
to filter host on device type.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The allowed values of the vnic-type in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.network.model.VIF&lt;/span&gt;&lt;/code&gt; class
will be extended. The allowed values of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_type&lt;/span&gt;&lt;/code&gt; column in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pci_devices&lt;/span&gt;&lt;/code&gt; table will be extended.&lt;/p&gt;
&lt;p&gt;Optionally, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIFMigrateData&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; object can be
extended to denote the destination host support transparent vDPA live
migration. This is optional as currently it would always be false until a QEMU
and libvirt version are released that support this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The neutron port-binding extension vnic-types has been extended
to add vnic-type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vdpa&lt;/span&gt;&lt;/code&gt;. No nova API changes are required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;vDPA ports will work like SR-IOV ports from an end user perspective,
however the device model presented to the guest will be a virtio NIC
and live migration will initially be blocked until supported by QEMU.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The performance will be the same as SR-IOV
in terms of dataplane performance and nova scheduling or VM creation
a.k.a. None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;vDPA requires a very new kernel and very new versions of QEMU and libvirt to
use.  Initial support for vDPA was added in kernel 5.7, QEMU 5.1 and
libvirt 6.9.0.&lt;/p&gt;
&lt;p&gt;The operator will need to ensure all dependencies are present to use
this feature. Intel NIC support is present in 5.7 at the time of writing,
no NIC that support vDPA is available on the market from Intel.
The first publicly available NICs with vDPA capabilities are the
Mellanox/Nvidia ConnectX-6 DX/LX NICs, which are only enabled in kernel 5.9&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephen.finucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update libvirt driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add prefilter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;libvirt 6.9.0+&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU 5.1+&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Linux 5.7+&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This will be tested primarily via unit and functional tests,
however a Tempest job using the vDPA sim module may be created
if it proves practical to do so. The main challenges to this are
creating a stable testing environment with the required dependencies.
Fedora rawhide has all the required dependencies but ships with python 3.9.
OpenStack currently does not work properly under python 3.9&lt;/p&gt;
&lt;p&gt;Alternative test environments such as Ubuntu 20.04 do not provide new enough
kernel by default or do not ship the required libvirt and QEMU versions.
Compilation from source is an option but we may or may not want to do that in
the upstream CI.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The existing admin networking document will be extended to introduce vDPA
and describe the requirement for use.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;The nova-neutron PTG discussion on this topic can be found on line 186
here: &lt;a class="reference external" href="https://etherpad.opendev.org/p/r.321f34cf3eb9caa9d87a9ec8349c3d29"&gt;https://etherpad.opendev.org/p/r.321f34cf3eb9caa9d87a9ec8349c3d29&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An introduction to this topic and is available as a blog at
&lt;a class="reference external" href="https://www.redhat.com/en/blog/introduction-vdpa-kernel-framework"&gt;https://www.redhat.com/en/blog/introduction-vdpa-kernel-framework&lt;/a&gt;
and other blogs on the topic covering the evolution and current state
are also available &lt;a class="reference external" href="https://www.redhat.com/en/blog?search=vdpa"&gt;https://www.redhat.com/en/blog?search=vdpa&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated to reflect changes to HTTP error codes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 18 Mar 2021 00:00:00 </pubDate></item><item><title>Configurable Instance Hostnames</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/configurable-instance-hostnames.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/configurable-instance-hostnames"&gt;https://blueprints.launchpad.net/nova/+spec/configurable-instance-hostnames&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow users to specify an explicit hostname for their instance when creating
instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nova publishes hostnames for instances via the metadata service and config
drives. This hostname is based on a sanitized version of the instance display
name combined with the domain value specified in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[api]&lt;/span&gt; &lt;span class="pre"&gt;dhcp_domain&lt;/span&gt;&lt;/code&gt;. As part
of the discussion around &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1581977"&gt;bug 1581977&lt;/a&gt;, it was noted that there is currently
no way to explicitly specify a hostname and decouple it from the display name.
We use the instance’s hostname when &lt;a class="reference external" href="https://docs.openstack.org/neutron/victoria/admin/config-dns-int.html"&gt;DNS integration is enabled in neutron&lt;/a&gt;,
and this can result in a lack of control over hostnames, preventing users doing
reasonable things like naming their instances based on the fully-qualified
domain name that the instance will eventually be available at.&lt;/p&gt;
&lt;p&gt;Correct this gap by allowing users to specify an explicit hostname when
creating instances.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user, I wish to specify an explicit hostname rather than relying on a
(poorly) sanitized version of the display name.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Allow users to pass an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; field when creating new
server(s) (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;) and when updating an existing server
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{id}&lt;/span&gt;&lt;/code&gt;). This &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute will have the following
constraints:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It must be 63 characters or less&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It must consist of alphanumeric characters and dashes (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-&lt;/span&gt;&lt;/code&gt;). Periods,
underscores, and other characters outside this set will be rejected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It cannot end in a dash&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where multiple instances are requested, hostnames will be suffixed with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-{idx}&lt;/span&gt;&lt;/code&gt;, where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{idx}&lt;/span&gt;&lt;/code&gt; is a 1-based index. If the combined name and suffix
would exceed the 63 character limit, the name will be rejected.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-EXT-SRV-ATTR:hostname&lt;/span&gt;&lt;/code&gt; instance attribute, which is currently
admin-only, will now be shown for non-admin users, since it doesn’t make sense
to allow users to configure the value but not see it.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove support for neutron’s DNS integration features and require users
explicitly create and configure ports with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; attribute before
creating the instance. This places extra work on nova and will result in a
worse user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbid creation of multiple instances when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute is
provided, similar to how we forbid this when a port is provided. This is
reasonable but will require a little more effort from users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start rejecting instance names that are not valid hostnames. This is a
significant breaking change that will impact many users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Instance&lt;/span&gt;&lt;/code&gt; object and corresponding database model and table
already have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; field/column.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new microversion will be introduced. When this microversion is used,
users will be able to pass an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; field when creating new
server(s) (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;) and when updating an existing server
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{id}&lt;/span&gt;&lt;/code&gt;). This &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute will have the following
constraints:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It must be 63 characters or less&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It must consist of alphanumeric characters and dashes (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-&lt;/span&gt;&lt;/code&gt;). Periods,
underscores, and other characters outside this set will be rejected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It cannot end in a dash&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where multiple instances are requested, hostnames will be suffixed with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-{idx}&lt;/span&gt;&lt;/code&gt;, where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{idx}&lt;/span&gt;&lt;/code&gt; is a 1-based index. If the combined name and suffix
would exceed the 63 character limit, the name will be rejected.&lt;/p&gt;
&lt;p&gt;When updating the hostname of an existing instance, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dns_name&lt;/span&gt;&lt;/code&gt; attribute
of the port(s) in neutron will be updated, as will the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hostname&lt;/span&gt;&lt;/code&gt; attribute
exposed via the metadata service.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-EXT-SRV-ATTR:hostname&lt;/span&gt;&lt;/code&gt; instance attribute, which is currently
admin-only, will now be accessible by non-admin users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None. Hostnames will be validated by both the nova API and neutron to prevent
invalid hostnames.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The neutron documentation will need to be updated to reflect the changes in
behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make necessary changes to nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update neutron documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested via Tempest tests, though this will likely require the
&lt;a class="reference external" href="https://github.com/openstack/designate-tempest-plugin"&gt;designate-tempest-plugin&lt;/a&gt; package. The bulk of the lifting will be done
with functional and unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Both nova and neutron’s documentation will need to be updated to reference this
functionality. The api-ref will be updated to document the new fields allowed
in the API requests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1581977"&gt;https://bugs.launchpad.net/nova/+bug/1581977&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/nova/+/764482"&gt;https://review.opendev.org/c/openstack/nova/+/764482&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2020-November/019113.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2020-November/019113.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Fri, 22 Jan 2021 00:00:00 </pubDate></item><item><title>libvirt driver support for flavor and image defined ephemeral encryption</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/ephemeral-encryption-libvirt.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption"&gt;https://blueprints.launchpad.net/nova/+spec/ephemeral-storage-encryption&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the specific libvirt virt driver implementation to support
the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The libvirt virt driver currently provides very limited support for ephemeral
disk encryption through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LVM&lt;/span&gt;&lt;/code&gt; imagebackend and the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PLAIN&lt;/span&gt;&lt;/code&gt;
encryption format provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As outlined in the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
spec this current implementation is controlled through compute host
configurables and is transparent to end users, unlike block storage volume
encryption via Cinder.&lt;/p&gt;
&lt;p&gt;With the introduction of the Flavor and Image defined ephemeral storage
encryption &lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we can now implement support for encrypting ephemeral
disks via images and flavors, allowing support for newer encryption formats
such as &lt;cite&gt;LUKSv1&lt;/cite&gt;. This also has the benefit of being natively supported by
&lt;cite&gt;QEMU&lt;/cite&gt;, as already seen in the libvirt driver when attaching  &lt;cite&gt;LUKSv1&lt;/cite&gt;
encrypted volumes provided by Cinder.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to request that all
of my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud with libvirt based computes I want to be able to pick
how my ephemeral storage be encrypted at rest through the selection of a
specific flavor or image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want each encrypted ephemeral disk attached to my instance to
have a separate unique secret associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to allow users to request that the ephemeral storage of
their instances is encrypted using the flexible &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="deprecate-the-legacy-implementation-within-the-libvirt-driver"&gt;
&lt;h3&gt;Deprecate the legacy implementation within the libvirt driver&lt;/h3&gt;
&lt;p&gt;The legacy implementation using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; within the libvirt virt driver
needs to be deprecated ahead of removal in a future release, this includes the
following options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/enabled&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/cipher&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ephemeral_storage_encryption]/key_size&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Limited support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; will be introduced using the new framework
before this original implementation is removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="populate-disk-info-with-encryption-properties"&gt;
&lt;h3&gt;Populate disk_info with encryption properties&lt;/h3&gt;
&lt;p&gt;The libvirt driver has an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; dict built from the contents
of the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_info&lt;/span&gt;&lt;/code&gt; and image metadata associated
with an instance. With the introduction of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DriverImageBlockDevice&lt;/span&gt;&lt;/code&gt;
within the Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec we
can now avoid the need to look again at image metadata while also adding some
ephemeral encryption related metadata to the dict.&lt;/p&gt;
&lt;p&gt;This dict currently contains the following:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by disks&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cdrom_bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The default bus used by cd-rom drives&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A nested dict keyed by disk name including information about each disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Each item within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mapping&lt;/span&gt;&lt;/code&gt; dict containing following keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bus&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The bus for this disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dev&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The device name for this disk as known to libvirt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A type from the BlockDeviceType enum (‘disk’, ‘cdrom’,’floppy’,
‘fs’, or ‘lun’)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;It can also contain the following optional keys:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Used to format swap/ephemeral disks before passing to instance (e.g.
‘swap’, ‘ext4’)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;boot_index&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The 1-based boot index of the disk.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In addition to the above this spec will also optionally add the following keys
for encrypted disks:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_format&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The encryption format used by the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_options&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A dict of encryption options&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;encryption_secret_uuid&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The UUID of the encryption secret associated with the disk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="handle-ephemeral-disk-encryption-within-imagebackend"&gt;
&lt;h3&gt;Handle ephemeral disk encryption within imagebackend&lt;/h3&gt;
&lt;p&gt;With the above in place we can now add encryption support within each image
backend.  As highlighted at the start of this spec this initial support will
only be for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; encryption format.&lt;/p&gt;
&lt;p&gt;Generic key management code will be introduced into the base
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class and used to create and store the
encryption secret within the configured key manager. The initial &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;
support will store a passphrase for each disk within the key manager. This is
unlike the current ephemeral storage encryption or encrypted volume
implementations that currently store a symmetric key in the key manager. This
remains a long running piece of technical debt in the encrypted volume
implementation as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; does not directly encrypt data with the provided
key.&lt;/p&gt;
&lt;p&gt;The base &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image&lt;/span&gt;&lt;/code&gt; class will also be extended
to accept and store the optional encryption details provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt;
above including the format, options and secret UUID.&lt;/p&gt;
&lt;p&gt;Each backend will then be modified to encrypt disks during
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.imagebackend.Image.create_image&lt;/span&gt;&lt;/code&gt; using the provided
format, options and secret.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="enable-the-compute-ephemeral-encryption-luks-trait"&gt;
&lt;h3&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Finally, with the above support in place the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; traits can be enabled when using a
backend that supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;. This will in turn enable scheduling to the
compute of any user requests asking for ephemeral storage encryption using the
format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue to use the transparent host configurables and expand support to other
encryption formats such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKS&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;As discussed above the ephemeral encryption keys will be added to the disk_info
for individual disks within the libvirt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This should hopefully be positive given the unique secret per disk and user
visible choice regarding how their ephemeral storage is encrypted at rest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users will now need to opt-in to ephemeral storage encryption being used by
their instances through their choice of image or flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;QEMU will natively decrypted these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; ephemeral disks for us using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libgcrypt&lt;/span&gt;&lt;/code&gt; library. While there have been performance issues with this in
the past workarounds &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can be implemented that use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dm-crypt&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This spec will aim to implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for all imagebackends but in
the future any additional encryption formats supported by these backends will
need to ensure matching traits are also enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The legacy implementation is deprecated but will continue to work for the time
being. As the new implementation is separate there is no further upgrade
impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;N/A&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Populate the individual disk dicts within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_info&lt;/span&gt;&lt;/code&gt; with any
ephemeral encryption properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide these properties to the imagebackends when creating each disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; based encryption within the imagebackends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_EPHEMERAL_ENCRYPTION_LUKS&lt;/span&gt;&lt;/code&gt; trait when the selected
imagebackend supports &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Flavor and Image defined ephemeral storage encryption &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unlike the parent spec once imagebackends support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; and enable the
required trait we can introduce Tempest based testing of this implementation in
addition to extensive functional and unit based tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New user documentation around the specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LUKSv1&lt;/span&gt;&lt;/code&gt; support for ephemeral
encryption within the libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference documentation around the changes to the virt block device layer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/ephemeral-encryption.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/ephemeral-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1"&gt;https://docs.openstack.org/nova/victoria/configuration/config.html#workarounds.disable_native_luksv1&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 19 Jan 2021 00:00:00 </pubDate></item><item><title>Remove tenant_id</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/remove-tenant-id.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/remove-tenant-id"&gt;https://blueprints.launchpad.net/nova/+spec/remove-tenant-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The blueprint proposes to remove the API interface that uses
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and replace it with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Nova API supports both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;,
which is unfriendly to users.&lt;/p&gt;
&lt;p&gt;The following is a confusing question.
By default, we support filtering instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt; &lt;span class="pre"&gt;(Optional)&lt;/span&gt;&lt;/code&gt;,
but through this parameter, we get a list of all instances that they
cannot get instances by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can see from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1185290"&gt;bug 1185290&lt;/a&gt; that when using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt;&lt;/code&gt; command,
if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; is required, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; must appear, as description
in &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, which is somewhat unintuitive.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;a class="footnote-reference brackets" href="#id3" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; mainly said: “As explained in lp:#1185290, if &lt;cite&gt;all_tenants&lt;/cite&gt;
is not passed we must ignore the &lt;cite&gt;tenant_id&lt;/cite&gt; search option.”.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can know from &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1468992"&gt;bug 1468992&lt;/a&gt; that many users want to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;
filtering instances, and using the concept of tenants in many of our
large-scale customer scenarios, they hope we can filter the expected
instances through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an (admin) user, I would like to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; uniformly in nova api,
instead of supporting both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to the request or response parameter changes API.&lt;/p&gt;
&lt;p&gt;Remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; field, using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt;
parameter, and then remove``all_tenants`` parameter in the following APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The keyword &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; in the path will be replaced with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; as below
APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;GET /os-simple-tenant-usage/{tenant_id}&lt;/cite&gt; APIs will be renamed to
&lt;cite&gt;GET /os-simple-project-usage/{project_id}&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We should block change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; below the deprecated APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups (List Security Groups)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-security-groups/{security_group_id} (Show Security Group Details)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-security-groups/{security_group_id} (Update Security Group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /os-security-group-rules (Create Security Group Rule)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-fping?all_tenants=1 (Ping Instances)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, tenant* reference will be replaced with project* in all policies,
code and docs too.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Add a new microversion.&lt;/p&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; parameter, and remove
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers (List Servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in request body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /limits (Show Rate And Absolute Limits)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id} (Show A Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-quota-sets/{tenant_id} (Update Quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/defaults (List Default Quotas For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-quota-sets/{tenant_id}/detail (Show The Detail of Quota)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-cells (List Cells)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in response body in follow APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/detail (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id} (List Server Detailed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /servers/{server_id} (Update Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action (Rebuild Server (rebuild Action))&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-security-groups (List Security Groups By Server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;GET /flavors/{flavor_id}/os-flavor-access (List Flavor Access Information&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;For Given Flavor)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Add Flavor Access To Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(addTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;POST /flavors/{flavor_id}/action (Remove Flavor Access From Tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(removeTenantAccess Action))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage (List Tenant Usage Statistics For All Tenants)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-simple-tenant-usage/{tenant_id} (Show Usage Statistics For Tenant)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Update openstacksdk, python-novaclient and python-openstackclient
for the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_tenants&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;all_projects&lt;/span&gt;&lt;/code&gt; in relate APIs,
policies and code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the python-novaclient , python-openstackclient and openstacksdk,
just support requesting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; in related APIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test for negative scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test (API samples).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary for this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the API reference for the new microversion, and update all uses of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt;&lt;/code&gt; in all docs and code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Mainly info: &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295"&gt;https://opendev.org/openstack/nova/src/branch/stable/ussuri/nova/api/openstack/compute/servers.py#L294-L295&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 31 Dec 2020 00:00:00 </pubDate></item><item><title>Nova provides remote console with password authentication</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/nova-support-webvnc-with-password-authentication.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-support-webvnc-with-password-authentication"&gt;https://blueprints.launchpad.net/nova/+spec/nova-support-webvnc-with-password-authentication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The feature aims at providing a safer remote console with password
authentication. End users can set console password for their instances.
Any user trying to access the password-encrypted console of instance
will get a locked window from web console prompting for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt;
input, and this provides almost the same experience as using VNC clients
(e.g vncviewer) to access vnc servers that require password authentication.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is only a token authentication against nova novncproxy, with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;token&lt;/span&gt;&lt;/code&gt; parameter appended to the request access_url. While this is
convenient, anyone who (e.g. A cloud administrator with too much curiosity
about tenants’ business) gets the access_url info will have access to
operating the instance by the web console directly, which is not that safe.&lt;/p&gt;
&lt;p&gt;Now an implementation for remote console with password authentication
will prevent malicious users from using the instance when failing to pass
password authentication, even if they had got the access_url.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The end user can set a remote console password to avoid the console access
url stolen by other user. And end user can reset console password when
he forgets.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to python-novaclient (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt;
subcommand) and equivalent in python-openstackclient to provide
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--password&lt;/span&gt;&lt;/code&gt; for reseting remote console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to nova-api when creating remote console:
Extra logic will be added to handle both cases(console password
provided, and not). If password is not provided, we see it as the
existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Create&lt;/span&gt; &lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt;&lt;/code&gt; operation, then it jumps to old
logic. Or we know it’s a request to reset password for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt;&lt;/code&gt;, and RPC call will be sent to compute service to
reset console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to nova-compute and virt driver to handle
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Reset&lt;/span&gt; &lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt; &lt;span class="pre"&gt;Password&lt;/span&gt;&lt;/code&gt; request. And this’s only implment
for libvirt driver. For other virt drivers, NotImplement will raise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to nova-novncproxy: auth schemes(e.g:rfb.VNC)
will be added. For the fact that project &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;noVNC&lt;/span&gt;&lt;/code&gt; has already provided
native support for password authentication(RFB version negotiation,
handshakes and password authentication), so rfb.VNC can escape from
these jobs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;New booting parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;console_password&lt;/span&gt;&lt;/code&gt; will be added to launch instances.
And the password will be used to assemble &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;graphics&lt;/span&gt;&lt;/code&gt; tag in libvirt XML.
In this way, password-encrypted remote console will be implemented.
The shortcoming of this implement is that no API provided to reset console
password after instance is booted.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;New microversion will be added to provide extra &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; parameter
for the Create Remote Console API.&lt;/p&gt;
&lt;p&gt;URL: /servers/{server_id}/remote-consoles&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request method: POST(update password for remote console)
Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; param to the request body&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the Create-Remote-Console API:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;"remote_console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vnc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"novnc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"newpass"&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; is in common password format.
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; parameter is optional:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; is present, console password will be updated while
getting new access_url.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only &lt;cite&gt;vnc&lt;/cite&gt; and &lt;cite&gt;spice&lt;/cite&gt; console protocols/types support reseting
password. If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; and (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protocol&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;)
are provided, and protocol/type not in support list
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HttpBadRequest&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; will be returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And for unsupported virt driver, &lt;cite&gt;HttpNotImplemented 501&lt;/cite&gt; will be
returned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Surely it will make web console safer. And note that console password will
only be securely kept by libvirtd and won’t be displayed in the result
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virsh&lt;/span&gt; &lt;span class="pre"&gt;dumpxml&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;instance&lt;/span&gt; &lt;span class="pre"&gt;UUID&amp;gt;&lt;/span&gt;&lt;/code&gt; or definition XMLs managed by libvirt
/qemu in local filesystem except. Briefly speaking, no potential security
risks will be introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;It does have impacts on end users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web GUI benefiting this feature allow end users to set/reset
console passwords for their instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When end users access password-encryted console of instances
via Web GUI, input for console password will be prompted from
web console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New &lt;cite&gt;get-*-console&lt;/cite&gt; CLIs may look like this(using nova command):&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;get-vnc-console&lt;span class="w"&gt; &lt;/span&gt;--vnc-password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'newpasswd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;VM&lt;span class="w"&gt; &lt;/span&gt;UUID&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;get-spice-console&lt;span class="w"&gt; &lt;/span&gt;--vnc-password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'newpasswd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;VM&lt;span class="w"&gt; &lt;/span&gt;UUID&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;New option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt; is added to auth_schemes list in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt;
segment in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt;. This allows nova-novncproxy to
detect and load rfb.VNC auth scheme.&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[vnc]&lt;/span&gt;
&lt;span class="na"&gt;auth_schemes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;none,vnc,vencrypt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;We should bump service object version and rpc version
for the ‘get_*_console’ rpc call. Then only when the
cluster fully upgrade to Ussuri release, the call can be
success. otherwise return failure for the request.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;pandatt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Alex Xu&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python-novaclient(and openstackclient as well): new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--password&lt;/span&gt;&lt;/code&gt; option will be added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt;
commands and some codes processing this value shall be added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-api: some codes to judge whether to call legacy
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt; API or to call remote compute service to
reset remote console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-compute: some codes to handle the request to reset console
password: reassemble graphics tag with password and update it to
libvirt XML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-novncproxy: some codes to implement rfb auth schemes,
security type negotiation (in current version, novncproxy tells
tenant_sock to use hardcoded &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc.AuthType.NONE&lt;/span&gt;&lt;/code&gt; when serving
as mediator between client and vnc server, though noVNC client
provides native support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc.AuthType.VNC&lt;/span&gt;&lt;/code&gt; with password
security handshake handle) and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security&lt;/span&gt; &lt;span class="pre"&gt;handshake&lt;/span&gt;&lt;/code&gt; (no-ops,
leave noVNC/websockify to do the stuff).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add releated unit test&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;Operation Guide&lt;/cite&gt; needs some updates, in #User-Facing Operations#
section.The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt; (or equivalent with openstack
CLI) provides &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--vnc-password&lt;/span&gt;&lt;/code&gt; option to user to reset console
console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;API Guides&lt;/cite&gt; needs no updates. However, some texts should be posted
to notify developers about how to benefit from this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;Configuration Reference&lt;/cite&gt; &amp;amp; &lt;cite&gt;Deployment Guides&lt;/cite&gt; need some updates.
A change in nova.conf to enable rfb.VNC auth scheme is added (nova
-novncproxy cares).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsGraphics"&gt;https://libvirt.org/formatdomain.html#elementsGraphics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1180092"&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1180092&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc6143"&gt;https://tools.ietf.org/html/rfc6143&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Virtual_Network_Computing"&gt;https://en.wikipedia.org/wiki/Virtual_Network_Computing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 25 Nov 2020 00:00:00 </pubDate></item><item><title>Nova provides remote console with password authentication</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/nova-support-webvnc-with-password-authentication.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-support-webvnc-with-password-authentication"&gt;https://blueprints.launchpad.net/nova/+spec/nova-support-webvnc-with-password-authentication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The feature aims at providing a safer remote console with password
authentication. End users can set console password for their instances.
Any user trying to access the password-encrypted console of instance
will get a locked window from web console prompting for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt;
input, and this provides almost the same experience as using VNC clients
(e.g vncviewer) to access vnc servers that require password authentication.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is only a token authentication against nova novncproxy, with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;token&lt;/span&gt;&lt;/code&gt; parameter appended to the request access_url. While this is
convenient, anyone who (e.g. A cloud administrator with too much curiosity
about tenants’ business) gets the access_url info will have access to
operating the instance by the web console directly, which is not that safe.&lt;/p&gt;
&lt;p&gt;Now an implementation for remote console with password authentication
will prevent malicious users from using the instance when failing to pass
password authentication, even if they had got the access_url.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The end user can set a remote console password to avoid the console access
url stolen by other user. And end user can reset console password when
he forgets.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to python-novaclient (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt;
subcommand) and equivalent in python-openstackclient to provide
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--password&lt;/span&gt;&lt;/code&gt; for reseting remote console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to nova-api when creating remote console:
Extra logic will be added to handle both cases(console password
provided, and not). If password is not provided, we see it as the
existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Create&lt;/span&gt; &lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt;&lt;/code&gt; operation, then it jumps to old
logic. Or we know it’s a request to reset password for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt;&lt;/code&gt;, and RPC call will be sent to compute service to
reset console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to nova-compute and virt driver to handle
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Reset&lt;/span&gt; &lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt; &lt;span class="pre"&gt;Password&lt;/span&gt;&lt;/code&gt; request. And this’s only implment
for libvirt driver. For other virt drivers, NotImplement will raise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be patched to nova-novncproxy: auth schemes(e.g:rfb.VNC)
will be added. For the fact that project &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;noVNC&lt;/span&gt;&lt;/code&gt; has already provided
native support for password authentication(RFB version negotiation,
handshakes and password authentication), so rfb.VNC can escape from
these jobs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;New booting parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;console_pasword&lt;/span&gt;&lt;/code&gt; will be added to launch instances.
And the password will be used to assemble &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;graphics&lt;/span&gt;&lt;/code&gt; tag in libvirt XML.
In this way, password-encrypted remote console will be implemented.
The shortcoming of this implement is that no API provided to reset console
password after instance is booted.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;New microversion will be added to provide extra &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; parameter
for the Create Remote Console API.&lt;/p&gt;
&lt;p&gt;URL: /servers/{server_id}/remote-consoles&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request method: POST(update password for remote console)
Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; param to the request body&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the Create-Remote-Console API:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;"remote_console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vnc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"novnc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"newpass"&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; is in common password format (not more than 8 characters,
see &lt;a class="reference external" href="http://people.redhat.com/pbonzini/qemu-test-doc/_build/html/topics/vnc_005fsecurity.html"&gt;vnc security&lt;/a&gt;).
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; parameter is optional:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; is present, console password will be updated while
getting new access_url.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only &lt;cite&gt;vnc&lt;/cite&gt; and &lt;cite&gt;spice&lt;/cite&gt; console protocols/types support reseting
password. If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; and (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protocol&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;)
are provided, and protocol/type not in support list
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HttpBadRequest&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; will be returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And for unsupported virt driver, &lt;cite&gt;HttpNotImplemented 501&lt;/cite&gt; will be
returned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Surely it will make web console safer. And note that console password will
only be securely kept by libvirtd and won’t be displayed in the result
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virsh&lt;/span&gt; &lt;span class="pre"&gt;dumpxml&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;instance&lt;/span&gt; &lt;span class="pre"&gt;UUID&amp;gt;&lt;/span&gt;&lt;/code&gt; or definition XMLs managed by libvirt
/qemu in local filesystem except. Briefly speaking, no potential security
risks will be introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;It does have impacts on end users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web GUI benefiting this feature allow end users to set/reset
console passwords for their instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When end users access password-encryted console of instances
via Web GUI, input for console password will be prompted from
web console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New &lt;cite&gt;get-*-console&lt;/cite&gt; CLIs may look like this(using nova command):&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;get-vnc-console&lt;span class="w"&gt; &lt;/span&gt;--vnc-password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'newpasswd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;VM&lt;span class="w"&gt; &lt;/span&gt;UUID&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;get-spice-console&lt;span class="w"&gt; &lt;/span&gt;--vnc-password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'newpasswd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;VM&lt;span class="w"&gt; &lt;/span&gt;UUID&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;New option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt; is added to auth_schemes list in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt;
segment in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt;. This allows nova-novncproxy to
detect and load rfb.VNC auth scheme.&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[vnc]&lt;/span&gt;
&lt;span class="na"&gt;auth_schemes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;none,vnc,vencrypt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;We should bump service object version and rpc version
for the ‘get_*_console’ rpc call. Then only when the
cluster fully upgrade to Victoria release, the call
can be success. otherwise return failure for the request.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;pandatt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Alex Xu&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python-novaclient(and openstackclient as well): new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--password&lt;/span&gt;&lt;/code&gt; option will be added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt;
commands and some codes processing this value shall be added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-api: some codes to judge whether to call legacy
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt; API or to call remote compute service to
reset remote console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-compute: some codes to handle the request to reset console
password: reassemble graphis tag with password and update it to
libvirt XML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-novncproxy: some codes to implement rfb auth schemes,
security type negotiation (in current version, novncproxy tells
tenant_sock to use hardcoded &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc.AuthType.NONE&lt;/span&gt;&lt;/code&gt; when serving
as mediator between client and vnc server, though noVNC client
provides native support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc.AuthType.VNC&lt;/span&gt;&lt;/code&gt; with password
security handshake handle) and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security&lt;/span&gt; &lt;span class="pre"&gt;handshake&lt;/span&gt;&lt;/code&gt; (no-ops,
leave noVNC/websockify to do the stuff).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add related unit test&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;Operation Guide&lt;/cite&gt; needs some updates, in #User-Facing Operations#
section.The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt; (or equivalent with openstack
CLI) provides &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--vnc-password&lt;/span&gt;&lt;/code&gt; option to user to reset console
console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;API Guides&lt;/cite&gt; needs no updates. However, some texts should be posted
to notify developers about how to benefit from this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;Configuration Reference&lt;/cite&gt; &amp;amp; &lt;cite&gt;Deployment Guides&lt;/cite&gt; need some updates.
A change in nova.conf to enable rfb.VNC auth scheme is added (nova
-novncproxy cares).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsGraphics"&gt;https://libvirt.org/formatdomain.html#elementsGraphics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1180092"&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1180092&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc6143"&gt;https://tools.ietf.org/html/rfc6143&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Virtual_Network_Computing"&gt;https://en.wikipedia.org/wiki/Virtual_Network_Computing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reposeposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 25 Nov 2020 00:00:00 </pubDate></item><item><title>Nova provides remote console with password authentication</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/approved/nova-support-webvnc-with-password-authentication.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-support-webvnc-with-password-authentication"&gt;https://blueprints.launchpad.net/nova/+spec/nova-support-webvnc-with-password-authentication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The feature aims at providing a safer remote console with password
authentication. End users can set console password for their instances.
Any user trying to access the password-encrypted console of instance
will get a locked window from web console prompting for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt;
input, and this provides almost the same experience as using VNC clients
(e.g vncviewer) to access vnc servers that require password authentication.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is only a token authentication against nova novncproxy, with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;token&lt;/span&gt;&lt;/code&gt; parameter appended to the request access_url. While this is
convenient, anyone who (e.g. A cloud administrator with too much curiosity
about tenants’ business) gets the access_url info will have access to
operating the instance by the web console directly, which is not safe.&lt;/p&gt;
&lt;p&gt;Now an implementation for remote console with password authentication
will prevent malicious users from using the instance when failing to pass
password authentication, even if they had got the access_url.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The end user can set a remote console password to avoid the console access
url stolen by other user. And end user can reset console password when
he forgets.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new microversion will be provided in the nova API (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt;
subcommand) and OSC will need to provide a specific version for reseting
remote console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The nova API will be extended to support console password when creating a
remote console.
There are two &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create&lt;/span&gt; &lt;span class="pre"&gt;console&lt;/span&gt;&lt;/code&gt; APIs. The first was only for the old
nova-consoles services (XenAPI-only) and was removed in Ussuri release &lt;a class="footnote-reference brackets" href="#id4" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.
The second, which is we will changes to support console password, is still
valid &lt;a class="footnote-reference brackets" href="#id5" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.
And the server actions for the other console &lt;a class="footnote-reference brackets" href="#id6" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, the console output
server action still need to be protected, and the deprecated action also
need to be blocked when the instance has a password set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be proposed to nova-compute and virt driver to handle
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Reset&lt;/span&gt; &lt;span class="pre"&gt;Remote&lt;/span&gt; &lt;span class="pre"&gt;Console&lt;/span&gt; &lt;span class="pre"&gt;Password&lt;/span&gt;&lt;/code&gt; request. And this’s only implement
for libvirt driver. For other virt drivers, NotImplement will raise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes will be proposed to nova-novncproxy: auth schemes(e.g:rfb.VNC)
will be added. For the fact that project &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;noVNC&lt;/span&gt;&lt;/code&gt; has already provided
native support for password authentication(RFB version negotiation,
handshakes and password authentication), so rfb.VNC can escape from
these jobs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;New booting parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;console_password&lt;/span&gt;&lt;/code&gt; will be added to launch instances.
And the password will be used to assemble &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;graphics&lt;/span&gt;&lt;/code&gt; tag in libvirt XML.
In this way, password-encrypted remote console will be implemented.
The shortcoming of this implement is that no API provided to reset console
password after instance is booted.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;New microversion will be added to provide extra &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; parameter
for the Create Remote Console API.&lt;/p&gt;
&lt;p&gt;URL: /servers/{server_id}/remote-consoles&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request method: POST(update password for remote console)
Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; param to the request body&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the Create-Remote-Console API:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;"remote_console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vnc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"novnc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"newpass"&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; is in common password format (not more than 8 characters,
see &lt;a class="reference external" href="http://people.redhat.com/pbonzini/qemu-test-doc/_build/html/topics/vnc_005fsecurity.html"&gt;vnc security&lt;/a&gt;).
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; parameter is optional:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; is present, console password will be updated while
getting new access_url.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only &lt;cite&gt;vnc&lt;/cite&gt; and &lt;cite&gt;spice&lt;/cite&gt; console protocols/types support reseting
password. If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;password&lt;/span&gt;&lt;/code&gt; and (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protocol&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt;)
are provided, and protocol/type not in support list
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HttpBadRequest&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; will be returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And for unsupported virt driver, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HttpBadRequest&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; will be
returned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Surely it will make web console safer. And note that console password will
only be securely kept by libvirtd and won’t be displayed in the result
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virsh&lt;/span&gt; &lt;span class="pre"&gt;dumpxml&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;Instance&lt;/span&gt; &lt;span class="pre"&gt;UUID&amp;gt;&lt;/span&gt;&lt;/code&gt; or definition XMLs managed by libvirt
/qemu in local filesystem except. Briefly speaking, no potential security
risks will be introduced.&lt;/p&gt;
&lt;p&gt;If we hard reboot the instance, it will be recreate XML when is booting,
and the old console will be disconnect. If you want to open the instance’s
console again, you can reset the password and open a new console.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;It does have impacts on end users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web GUI benefiting this feature allow end users to set/reset
console passwords for their instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When end users access password-encryted console of instances
via Web GUI, input for console password will be prompted from
web console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New &lt;cite&gt;get-*-console&lt;/cite&gt; CLIs may look like this(using nova command):&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;get-vnc-console&lt;span class="w"&gt; &lt;/span&gt;--vnc-password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'newpasswd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;VM&lt;span class="w"&gt; &lt;/span&gt;UUID&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;get-spice-console&lt;span class="w"&gt; &lt;/span&gt;--vnc-password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'newpasswd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;VM&lt;span class="w"&gt; &lt;/span&gt;UUID&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;New option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt; is added to auth_schemes list in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc&lt;/span&gt;&lt;/code&gt;
segment in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt;. This allows nova-novncproxy to
detect and load rfb.VNC auth scheme.&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[vnc]&lt;/span&gt;
&lt;span class="na"&gt;auth_schemes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;none,vnc,vencrypt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;We should bump service object version and rpc version for the ‘get_*_console’
rpc call. Then only when the cluster fully upgrade to Wallaby release, the
call can be success. otherwise return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HttpBadRequest&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; for the request.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;songwenping&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python-novaclient(and openstackclient as well): new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--password&lt;/span&gt;&lt;/code&gt; option will be added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt;
commands and some codes processing this value shall be added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-api: some codes to judge whether to call legacy
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt; API or to call remote compute service to
reset remote console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-compute: some codes to handle the request to reset console
password: reassemble graphics tag with password and update it to
libvirt XML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-novncproxy: some codes to implement rfb auth schemes,
security type negotiation (in current version, novncproxy tells
tenant_sock to use hardcoded &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc.AuthType.NONE&lt;/span&gt;&lt;/code&gt; when serving
as mediator between client and vnc server, though noVNC client
provides native support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnc.AuthType.VNC&lt;/span&gt;&lt;/code&gt; with password
security handshake handle) and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security&lt;/span&gt; &lt;span class="pre"&gt;handshake&lt;/span&gt;&lt;/code&gt; (no-ops,
leave noVNC/websockify to do the stuff).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add related unit test&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;Operation Guide&lt;/cite&gt; needs some updates, in #User-Facing Operations#
section.The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;get-*-console&lt;/span&gt;&lt;/code&gt; (or equivalent with openstack
CLI) provides &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--vnc-password&lt;/span&gt;&lt;/code&gt; option to user to reset console
console password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;API Guides&lt;/cite&gt; needs no updates. However, some texts should be posted
to notify developers about how to benefit from this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;Configuration Reference&lt;/cite&gt; &amp;amp; &lt;cite&gt;Deployment Guides&lt;/cite&gt; need some updates.
A change in nova.conf to enable rfb.VNC auth scheme is added (nova
-novncproxy cares).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/#xenserver-vnc-proxy-xvp-consoles-os-consoles"&gt;https://docs.openstack.org/api-ref/compute/#xenserver-vnc-proxy-xvp-consoles-os-consoles&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=#server-consoles"&gt;https://docs.openstack.org/api-ref/compute/?expanded=#server-consoles&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=create-console-detail#get-vnc-console-os-getvncconsole-action-deprecated"&gt;https://docs.openstack.org/api-ref/compute/?expanded=create-console-detail#get-vnc-console-os-getvncconsole-action-deprecated&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsGraphics"&gt;https://libvirt.org/formatdomain.html#elementsGraphics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugzilla.redhat.com/show_bug.cgi?id=1180092"&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1180092&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://tools.ietf.org/html/rfc6143"&gt;https://tools.ietf.org/html/rfc6143&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Virtual_Network_Computing"&gt;https://en.wikipedia.org/wiki/Virtual_Network_Computing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 25 Nov 2020 00:00:00 </pubDate></item><item><title>I/O (PCIe) based NUMA scheduling</title><link>https://specs.openstack.org/openstack/nova-specs/specs/kilo/implemented/input-output-based-numa-scheduling.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/input-output-based-numa-scheduling"&gt;https://blueprints.launchpad.net/nova/+spec/input-output-based-numa-scheduling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I/O based NUMA scheduling will add support for intelligent NUMA node placement
for guests that have been assigned a host PCI device.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Modern servers with two or more processors have a Non Uniform Memory
Architecture (NUMA). This means that there are different memory performance
and latency characteristics when accessing memory directly attached to one
processor than when accessing memory directly attached to another processor in
the same server. Similarly, PCIe I/O devices such as Network Interface Cards
(NICs), can be more closely associated with one processor than another.&lt;/p&gt;
&lt;p&gt;The optimal configuration with multi NUMA node platforms is where all host
resources that the guest requires are associated with the same host NUMA node,
this will reduce or remove cross NUMA node memory traffic.&lt;/p&gt;
&lt;p&gt;To reach a remote NUMA node the memory request must traverse the inter CPU
link and use the remote NUMA nodes associated memory controller to access the
remote node. This incurs a latency penalty on remote NUMA node memory access.&lt;/p&gt;
&lt;p&gt;The default guest placement policy is to use any available physical CPU (pCPU)
from any NUMA node. This blueprint optimises Openstack guest placement by
ensuring that a guest bound to a PCI device is scheduled to run on a NUMA node
that is associated with the guests pCPU and memory allocation.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;A guest running workloads requires the use of networking and memory resources
from the host. For the use case where the guests resource requirements fit in
a single NUMA node, an optimally configured system all guest resources should
be associated with the same NUMA node. NFV represents an obvious use case for
when this is particularly important, but there are significant benefits for
other more “traditional” cloud and enterprise workloads.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="project-priority"&gt;
&lt;h3&gt;Project Priority&lt;/h3&gt;
&lt;p&gt;The kilo priorities list is currently not defined. However under the currently
proposed list of priorities it would fall under “Performance”.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Extend the PCI device model with a NUMA node field.&lt;/p&gt;
&lt;p&gt;Libvirt versions &amp;gt; 1.2.6 will provide the NUMA node of a host PCI device we
will store this information in the nova DB for use during the guest placement
phase.&lt;/p&gt;
&lt;p&gt;Extend the PCI device capabilities for libvirt config.&lt;/p&gt;
&lt;p&gt;Extend the libvirt driver to capture the PCI devices numa node.&lt;/p&gt;
&lt;p&gt;Extend PCI device tracker to track the PCI device NUMA node usage.&lt;/p&gt;
&lt;p&gt;Nova scheduling will be enhanced to take consideration of a guests PCI device
requirements and the nodes available for placement.&lt;/p&gt;
&lt;p&gt;The NUMA topology filter will be modified to ensure the guest is scheduled on
the requested host NUMA node.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Libvirt supports integration with a NUMA daemon (numad) that monitors NUMA
topology and usage. It attempts to locate guests for optimum NUMA locality,
dynamically adjusting to changing system conditions. This is insufficient
because we need this intelligence in nova for host selection and node
deployment.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The PciDevice model will be extended to add a field identifying the NUMA node
that PCI device is associated with.&lt;/p&gt;
&lt;p&gt;numa_node = Column(Integer, nullable=True)&lt;/p&gt;
&lt;p&gt;A DB migration script will use ALTER_TABLE to add a new column to the
pci_devices table in nova DB.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no change to the REST API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This blueprint does not introduce any new security issues.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;This blueprint does not introduce new notifications.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This blueprint adds no other end user impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Associating a guests PCI device and RAM allocation with the same NUMA node
provides an optimal configuration that will give improved I/O throughput and
reduced memory latencies, compared with the default libvirt guest placement
policy.&lt;/p&gt;
&lt;p&gt;This feature will add some scheduling overhead, but this overhead will deliver
improved performance on the host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;To use this feature the deployer must use HW that is capable of reporting
NUMA related info to the OS.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This blueprint will have no developer impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;James Chapman&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Przemyslaw Czesnowicz
Sean Mooney
Adrian Hoban&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a NUMA node attribute to the pci_device object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use libvirt to discover hosts PCI device NUMA node association&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable nova compute synchronise PCI device NUMA node associations with nova
DB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable libvirt driver configure guests with requested PCI device NUMA node
associations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the nova scheduler decide on which host is best able to support
a guest&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable libvirt driver decide on which NUMA node to place a guest&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The dependencies for this feature have been included in the Juno release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests will be added to validate these modifications.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This feature will not add a new scheduling filter, but rather extend the
existing NUMA topology filter. We will add documentation as required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 04 Nov 2020 00:00:00 </pubDate></item><item><title>Add support for encrypted emulated virtual TPM</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/add-emulated-virtual-tpm.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/add-emulated-virtual-tpm"&gt;https://blueprints.launchpad.net/nova/+spec/add-emulated-virtual-tpm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are a class of applications which expect to use a TPM device to store
secrets. In order to run these applications in a virtual machine, it would be
useful to expose a virtual TPM device within the guest. Accordingly, the
suggestion is to add flavor/image properties which a) translate to placement
traits for scheduling and b) cause such a device to be added to the VM by the
relevant virt driver.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there is no way to create virtual machines within nova that provide
a virtual TPM device to the guest.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Support the virtualizing of existing applications and operating systems which
expect to make use of physical TPM devices. At least one hypervisor
(libvirt/qemu) currently supports the creation of an emulated TPM device which
is associated with a per-VM &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swtpm&lt;/span&gt;&lt;/code&gt; process on the host, but there is no way
to tell nova to enable it.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In recent libvirt and qemu (and possibly other hypervisors as well) there is
support for an emulated vTPM device. We propose to modify nova to make use
of this capability.&lt;/p&gt;
&lt;p&gt;This spec describes only the libvirt implementation.&lt;/p&gt;
&lt;section id="xml"&gt;
&lt;h3&gt;XML&lt;/h3&gt;
&lt;p&gt;The desired libvirt XML arguments are something like this (&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsTpm"&gt;source&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;tpm&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'tpm-tis'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'emulator'&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'2.0'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;encryption&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'6dd3e4a5-1d76-44ce-961f-f119f5aad935'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;tpm&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="prerequisites"&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;Support for encrypted emulated TPM requires at least:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;libvirt version 5.6.0 or greater.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;qemu 2.11 at a minimum, though qemu 2.12 is recommended. The virt driver code
should add suitable version checks (in the case of LibvirtDriver, this would
include checks for both libvirt and qemu). Currently emulated TPM is only
supported for x86, though this is an implementation detail rather than an
architectural limitation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swtpm&lt;/span&gt;&lt;/code&gt; binary and libraries on the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access to a castellan-compatible key manager, such as barbican, for storing
the passphrase used to encrypt the virtual device’s data. (The key manager
implementation’s public methods must be capable of consuming the user’s auth
token from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt; parameter which is part of the interface.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access to an object-store service, such as swift, for storing the file the
host uses for the virtual device data during operations such as shelve.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="config"&gt;
&lt;h3&gt;Config&lt;/h3&gt;
&lt;p&gt;All of the following apply to the compute (not conductor/scheduler/API)
configs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A new config option will be introduced to act as a “master switch” enabling
vTPM. This config option would apply to future drivers’ implementations as
well, but since this spec and current implementation are specific to libvirt,
it is in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; rather than the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute&lt;/span&gt;&lt;/code&gt; group:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;[libvirt]
vtpm_enabled = $bool (default False)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To enable move operations (anything involving rebuilding a vTPM on a new
host), nova must be able to lay down the vTPM data with the correct ownership
– that of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swtpm&lt;/span&gt;&lt;/code&gt; process libvirt will create – but we can’t detect
what that ownership will be. Thus we need a pair of config options on the
compute indicating the user and group that should own vTPM data on that
host:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;[libvirt]
swtpm_user = $str (default 'tss')
swtpm_group = $str (default 'tss')
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Existing, known) options for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[key_manager]&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New standard keystoneauth1 auth/session/adapter options for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[swift]&lt;/span&gt;&lt;/code&gt; will
be introduced.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="traits-extra-specs-image-meta"&gt;
&lt;h3&gt;Traits, Extra Specs, Image Meta&lt;/h3&gt;
&lt;p&gt;In order to support this functionality we propose to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_TPM_1_2&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_SECURITY_TPM_2_0&lt;/span&gt;&lt;/code&gt; traits. These represent the two different
versions of the TPM spec that are currently supported. (Note that 2.0 is not
backward compatible with 1.2, so we can’t just ignore 1.2. A summary of the
differences between the two versions is currently available &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Trusted_Platform_Module#TPM_1.2_vs_TPM_2.0"&gt;here&lt;/a&gt;.) When all
the &lt;a class="reference internal" href="#prerequisites"&gt;Prerequisites&lt;/a&gt; have been met and the &lt;a class="reference internal" href="#config"&gt;Config&lt;/a&gt; switch is on, the libvirt
compute driver will set both of these traits on the compute node resource
provider.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support the following new flavor extra_specs and their corresponding image
metadata properties (which are simply &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;s/:/_/&lt;/span&gt;&lt;/code&gt; of the below):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_version={1.2|2.0}&lt;/span&gt;&lt;/code&gt;. This will be:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;translated to the corresponding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required=COMPUTE_SECURITY_TPM_{1_2|2_0}&lt;/span&gt;&lt;/code&gt; in the allocation candidate
request to ensure the instance lands on a host capable of vTPM at the
requested version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;used by the libvirt compute driver to inject the appropriate guest &lt;a class="reference internal" href="#xml"&gt;XML&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Whereas it would be possible to specify
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:COMPUTE_SECURITY_TPM_{1_2|2_0}=required&lt;/span&gt;&lt;/code&gt; directly in the
flavor extra_specs or image metadata, this would only serve to
land the instance on a capable host; it would not trigger the libvirt
driver to create the virtual TPM device. Therefore, to avoid
confusion, this will not be documented as a possibility.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm_model={TIS|CRB}&lt;/span&gt;&lt;/code&gt;. Indicates the emulated model to be used. If
omitted, the default is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TIS&lt;/span&gt;&lt;/code&gt; (this corresponds to the libvirt default).
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CRB&lt;/span&gt;&lt;/code&gt; is only compatible with TPM version 2.0; if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CRB&lt;/span&gt;&lt;/code&gt; is requested
with version 1.2, an error will be raised from the API.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To summarize, all and only the following combinations are supported, and are
mutually exclusive (none are inter-compatible):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Version 1.2, Model TIS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Version 2.0, Model TIS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Version 2.0, Model CRB&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that since the TPM is emulated (a process/file on the host), the
“inventory” is effectively unlimited. Thus there are no resource classes
associated with this feature.&lt;/p&gt;
&lt;p&gt;If both the flavor and the image specify a TPM trait or device model and the
two values do not match, an exception will be raised from the API by the
flavor/image validator.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="instance-lifecycle-operations"&gt;
&lt;h3&gt;Instance Lifecycle Operations&lt;/h3&gt;
&lt;p&gt;Descriptions below are libvirt driver-specific. However, it is left to the
implementation which pieces are performed by the compute manager vs. the
libvirt ComputeDriver itself.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In deciding whether/how to support a given operation, we use “How
does this work on baremetal” as a starting point. If we can support a
VM operation without introducing inordinate complexity or user-facing
weirdness, we do.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="spawn"&gt;
&lt;h4&gt;Spawn&lt;/h4&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Even though swift is not required for spawn, ensure a swift endpoint is
present in the service catalog (and reachable? version discovery?
implementation detail) so that a future unshelve doesn’t break the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova generates a random passphrase and stores it in the configured key
manager, yielding a UUID, hereinafter referred to as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$secret_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova saves the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$secret_uuid&lt;/span&gt;&lt;/code&gt; in the instance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; under
key &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virSecretDefineXML&lt;/span&gt;&lt;/code&gt; API to define a private (value can’t be
listed), ephemeral (state is stored only in memory, never on disk) secret
whose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; is the instance UUID, and whose UUID is the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$secret_uuid&lt;/span&gt;&lt;/code&gt;.
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virSecretSetValue&lt;/span&gt;&lt;/code&gt; API is then used to set its value to the generated
passphrase. We already provide a wrapper around this API at
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.host.Host.create_secret&lt;/span&gt;&lt;/code&gt; for use with encrypted volumes
and will expand this to cover vTPM also.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova injects the &lt;a class="reference internal" href="#xml"&gt;XML&lt;/a&gt; into the instance’s domain. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;model&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;version&lt;/span&gt;&lt;/code&gt; are gleaned from the flavor/image properties, and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;secret&lt;/span&gt;&lt;/code&gt;
is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$secret_uuid&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once libvirt has created the guest, nova uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virSecretUndefine&lt;/span&gt;&lt;/code&gt; API
to delete the secret. The instance’s emulated TPM continues to function.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Spawning from an image created by snapshotting a VM with a vTPM will
result in a fresh, empty vTPM, even if that snapshot was created by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shelve&lt;/span&gt;&lt;/code&gt;. By contrast, &lt;a class="reference internal" href="#spawn-during-unshelve"&gt;spawn during unshelve&lt;/a&gt; will restore such
vTPM data.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="cold-boot"&gt;
&lt;h4&gt;Cold Boot&lt;/h4&gt;
&lt;p&gt;…and any other operation that starts the guest afresh. (Depending on the &lt;a class="reference internal" href="#key-manager"&gt;key
manager&lt;/a&gt; security model, these may be restricted to the instance owner.)&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Pull the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$secret_uuid&lt;/span&gt;&lt;/code&gt; from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_uuid&lt;/span&gt;&lt;/code&gt; of the instance’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieve the passphrase associated with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$secret_uuid&lt;/span&gt;&lt;/code&gt; via the configured
key manager API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then perform steps 4-6 as described under &lt;a class="reference internal" href="#spawn"&gt;Spawn&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migrations-and-their-ilk"&gt;
&lt;h4&gt;Migrations and their ilk&lt;/h4&gt;
&lt;p&gt;For the libvirt implementation, the emulated TPM data is stored in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/libvirt/swtpm/&amp;lt;instance&amp;gt;&lt;/span&gt;&lt;/code&gt;. Certain lifecycle operations require
that directory to be copied verbatim to the “destination”. For (cold/live)
migrations, only the user that nova-compute runs as is guaranteed to be able to
have SSH keys set up for passwordless access, and it’s only guaranteed to be
able to copy files to the instance directory on the destination node. We
therefore propose the following procedure for relevant lifecycle operations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Copy the directory into the local instance directory, changing the ownership
to match it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform the move, which will automatically carry the data along.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change ownership back and move the directory out to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/libvirt/swtpm/&amp;lt;instance&amp;gt;&lt;/span&gt;&lt;/code&gt; on the destination.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On confirm/revert, delete the directory from the source/destination,
respectively. (This is done automatically by libvirt when the guest is torn
down.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On revert, the data directory must be restored (with proper permissions) on
the source.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since the expected ownership on the target may be different than on the source,
and is (we think) impossible to detect, the admin must inform us of it via the
new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]swtpm_user&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]swtpm_group&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#config"&gt;Config&lt;/a&gt; options if
different from the default of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tss&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This should allow support of cold/live migration and resizes that don’t change
the device.&lt;/p&gt;
&lt;div class="admonition-todo admonition" id="id1"&gt;
&lt;p class="admonition-title"&gt;Todo&lt;/p&gt;
&lt;p&gt;Confirm that the above “manual” copying around is actually necessary
for migration. It’s unclear from reading
&lt;a class="reference external" href="https://github.com/qemu/qemu/blob/6a5d22083d50c76a3fdc0bffc6658f42b3b37981/docs/specs/tpm.txt#L324-L383"&gt;https://github.com/qemu/qemu/blob/6a5d22083d50c76a3fdc0bffc6658f42b3b37981/docs/specs/tpm.txt#L324-L383&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Resize can potentially add a vTPM to an instance that didn’t have one before,
or remove the vTPM from an instance that did have one, and those should “just
work”. When resizing from one version/model to a different one the data can’t
and won’t carry over (for same-host resize, we must &lt;em&gt;remove&lt;/em&gt; the old backing
file). If both old and new flavors have the same model/version, we must ensure
we convey the virtual device data as described above (for same-host resize, we
must &lt;em&gt;preserve&lt;/em&gt; the existing backing file).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="shelve-offload-and-unshelve"&gt;
&lt;h4&gt;Shelve (offload) and Unshelve&lt;/h4&gt;
&lt;p&gt;Restoring vTPM data when unshelving a shelve-offloaded server requires the vTPM
data to be persisted somewhere. We can’t put it with the image itself, as it’s
data external to the instance disk. So we propose to put it in object-store
(swift) and maintain reference to the swift object in the instance’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The shelve operation needs to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Save the vTPM data directory to swift.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the swift object ID and digital signature (sha256) of the directory to
the instance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt; under the (new) &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_object_id&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_object_sha256&lt;/span&gt;&lt;/code&gt; keys.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the appropriate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_version&lt;/span&gt;&lt;/code&gt; and/or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_model&lt;/span&gt;&lt;/code&gt; metadata
properties on the image. (This is to close the gap where the vTPM on
original VM was created at the behest of image, rather than flavor,
properties. It ensures the proper scheduling on unshelve, and that the
correct version/model is created on the target.)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The unshelve operation on a shelved (but not offloaded) instance should “just
work” (except for deleting the swift object; see below). The code path for
unshelving an offloaded instance needs to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Ensure we land on a host capable of the necessary vTPM version and model
(we get this for free via the common scheduling code paths, because we did
step 3 during shelve).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Look for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_object_{id|sha256}&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_secret_uuid&lt;/span&gt;&lt;/code&gt; in the
instance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download the swift object. Validate its checksum and fail if it doesn’t
match.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign ownership of the data directory according to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]swtpm_{user|group}&lt;/span&gt;&lt;/code&gt; on the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieve the secret and feed it to libvirt; and generate the appropriate
domain XML (we get this for free via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spawn()&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the object from swift, and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_object_{id|sha256}&lt;/span&gt;&lt;/code&gt; from the
instance &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata&lt;/span&gt;&lt;/code&gt;. This step must be done from both code paths
(i.e. whether the shelved instance was offloaded or not).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;There are a couple of ways a user can still “outsmart” our checks and
make horrible things happen on unshelve. For example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The flavor specifies no vTPM properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;original&lt;/em&gt; image specified version 2.0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Between shelve and unshelve, edit the snapshot to specify version
1.2.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will happily create a v1.2 vTPM and restore the (v2.0) data into
it. The VM will (probably) boot just fine, but unpredictable things
will happen when the vTPM is accessed.&lt;/p&gt;
&lt;p&gt;We can’t prevent &lt;em&gt;all&lt;/em&gt; stupidity.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As mentioned in &lt;a class="reference internal" href="#security-impact"&gt;Security impact&lt;/a&gt;, if shelve is performed by the
admin, only the admin will be able to perform the corresponding
unshelve operation. And depending on the &lt;a class="reference internal" href="#key-manager"&gt;key manager&lt;/a&gt; security
model, if shelve is performed by the user, the admin may not be able
to perform the corresponding unshelve operation.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Since the backing device data is virt driver-specific, it must be managed by
the virt driver; but we want the object-store interaction to be done by compute
manager. We therefore propose the following interplay between compute manager
and virt driver:&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeDriver.snapshot()&lt;/span&gt;&lt;/code&gt; contract currently does not specify a return
value. It will be changed to allow returning a file-like with the (prepackaged)
backing device data. The libvirt driver implementation will open a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tar&lt;/span&gt;&lt;/code&gt; pipe
and return that handle. The compute manager is responsible for reading from
that handle and pushing the contents into the swift object. (Implementation
detail: we only do the swift thing for snapshots during shelve, so a) the virt
driver should not produce the handle except when the VM is in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHELVE[_OFFLOADED]&lt;/span&gt;&lt;/code&gt; state; and/or the compute manager should explicitly
close the handle from other invocations of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;snapshot()&lt;/span&gt;&lt;/code&gt;.)&lt;/p&gt;
&lt;p id="spawn-during-unshelve"&gt;The compute driver touchpoint for unshelving an offloaded instance is
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spawn()&lt;/span&gt;&lt;/code&gt;. This method will get a new kwarg which is a file-like. If not
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, virt driver implementations are responsible for streaming from that
handle and reversing whatever was done during &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;snapshot()&lt;/span&gt;&lt;/code&gt; (in this case un-&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tar&lt;/span&gt;&lt;/code&gt;-ing). For the unshelve path for offloaded instances, the compute
manager will pull down the swift object and stream it to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spawn()&lt;/span&gt;&lt;/code&gt; via this
kwarg.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="createimage-and-createbackup"&gt;
&lt;h4&gt;createImage and createBackup&lt;/h4&gt;
&lt;p&gt;Because vTPM data is associated with the &lt;strong&gt;instance&lt;/strong&gt;, not the &lt;strong&gt;image&lt;/strong&gt;, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createImage&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createBackup&lt;/span&gt;&lt;/code&gt; flows will not be changed. In particular,
they will not attempt to save the vTPM backing device to swift.&lt;/p&gt;
&lt;p&gt;This, along with the fact that fresh &lt;a class="reference internal" href="#spawn"&gt;Spawn&lt;/a&gt; will not attempt to restore vTPM
data (even if given an image created via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shelve&lt;/span&gt;&lt;/code&gt;)  also prevents “cloning”
of vTPMs.&lt;/p&gt;
&lt;p&gt;This is analogous to the baremetal case, where spawning from an image/backup on
a “clean” system would get you a “clean” (or no) TPM.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rebuild"&gt;
&lt;h4&gt;Rebuild&lt;/h4&gt;
&lt;p&gt;Since the instance is staying on the same host, we have the ability to leave
the existing vTPM backing file intact. This is analogous to baremetal behavior,
where restoring a backup on an existing system will not touch the TPM (or any
other devices) so you get whatever’s already there. However, it is also
possible to lock your instance out of its vTPM by rebuilding with a different
image, and/or one with different metadata. A certain amount of responsibility
is placed on the user to avoid scenarios like using the TPM to create a master
key and not saving that master key (in your rebuild image, or elsewhere).&lt;/p&gt;
&lt;p&gt;That said, rebuild will cover the following scenarios:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If there is no existing vTPM backing data, and the rebuild image asks for a
vTPM, create a fresh one, just like &lt;a class="reference internal" href="#spawn"&gt;Spawn&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there is an existing vTPM and neither the flavor nor the image asks for
one, delete it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there is an existing vTPM and the flavor or image asks for one, leave the
backing file alone. However, if different versions/models are requested by
the old and new image in combination with the flavor, we will fail the
rebuild.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="evacuate"&gt;
&lt;h4&gt;Evacuate&lt;/h4&gt;
&lt;p&gt;Because the vTPM data belongs to libvirt rather than being stored in the
instance disk, the vTPM is lost on evacuate, &lt;em&gt;even if the instance is
volume-backed&lt;/em&gt;. This is analogous to baremetal behavior, where the (hardware)
TPM is left behind even if the rest of the state is resurrected on another
system via shared storage.&lt;/p&gt;
&lt;p&gt;(It may be possible to mitigate this by mounting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/lib/libvirt/swtpm/&lt;/span&gt;&lt;/code&gt; on
shared storage, though libvirt’s management of that directory on guest
creation/teardown may stymie such attempts. This would also bring in additional
security concerns. In any case, it would be an exercise for the admin; nothing
will be done in nova to support or prevent it.)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="destroy"&gt;
&lt;h4&gt;Destroy&lt;/h4&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Delete the key manager secret associated with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata['tpm_secret_uuid']&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libvirt deletes the vTPM data directory as part of guest teardown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system_metadata['tpm_object_id']&lt;/span&gt;&lt;/code&gt; exists, the &lt;em&gt;API side&lt;/em&gt; will delete
the swift object it identifies. Since this metadata only exists while an
instance is shelved, this should only be applicable in corner cases like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destroy()&lt;/span&gt;&lt;/code&gt; is performed between shelve and offload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleaning up a VM in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; state from a shelve, offload, or unshelve
that failed (at just the right time).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleaning up a VM that is deleted while the host was down.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="limitations"&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;p&gt;This is a summary of odd or unexpected behaviors resulting from this design.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Except for migrations and shelve-offload, vTPM data sticks with the
instance+host. In particular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;vTPM data is lost on &lt;a class="reference internal" href="#evacuate"&gt;Evacuate&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;vTPM data is not carried with “reusable snapshots”
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createBackup&lt;/span&gt;&lt;/code&gt;/&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createImage&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The ability of instance owners or admins to perform certain instance
lifecycle operations may be limited depending on the &lt;a class="reference internal" href="#security-impact"&gt;security model&lt;/a&gt; used for the &lt;a class="reference internal" href="#key-manager"&gt;key manager&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since secret management is done by the virt driver, deleting an
instance when the compute host is down can orphan its secret. If the host
comes back up, the secret will be reaped when compute invokes the virt
driver’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;destroy&lt;/span&gt;&lt;/code&gt;. But if the host never comes back up, it would have to
be deleted manually.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Rather than using a trait, we could instead use arbitrarily large inventories
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;1_2&lt;/span&gt;&lt;/code&gt;/&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;2_0&lt;/span&gt;&lt;/code&gt; resource classes. Unless it can be shown that there’s an
actual limit we can discover, this just isn’t how we do things.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instead of using specialized &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:tpm*&lt;/span&gt;&lt;/code&gt; extra_spec/image_meta properties,
implicitly configure based on the placement-ese syntax
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:COMPUTE_SECURITY_TPM_*&lt;/span&gt;&lt;/code&gt;). Rejected because we’re trying to move
away from this way of doing things in general, preferring instead to support
syntax specific to the feature, rather than asking the admin to understand
how the feature maps to placement syntax. Also, whereas in some cases the
mapping may be straightforward, in other cases additional configuration is
required at the virt driver level that can’t be inferred from the placement
syntax, which would require mixing and matching placement and non-placement
syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That being the case, forbid placement-ese syntax using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources[$S]:COMPUTE_SECURITY_TPM_*&lt;/span&gt;&lt;/code&gt;. Rejected mainly due to the
(unnecessary) additional complexity, and because we don’t want to get in the
business of assuming there’s no use case for “land me on a vTPM (in)capable
host, but don’t set one up (yet)”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use physical passthrough (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;backend&lt;/span&gt; &lt;span class="pre"&gt;type='passthrough'&amp;gt;&lt;/span&gt;&lt;/code&gt;) of a real
(hardware) TPM device. This is not feasible with current TPM hardware because
(among other things) changing ownership of the secrets requires a host
reboot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Block the operations that require object store. This is deemed nonviable,
particularly since cross-cell resize uses shelve under the covers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use glance or the key manager instead of swift to store the vTPM data for
those operations. NACKed because those services really aren’t intended for
that purpose, and (at least glance) may block such usages in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save vTPM data on any snapshot operation (including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createImage&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;createBackup&lt;/span&gt;&lt;/code&gt;). This adds complexity as well as some unintended behaviors,
such as the ability to “clone” vTPMs. Users will be less surprised when their
vTPM acts like a (hardware) TPM in these cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rather than checking for swift at spawn time, add an extra spec / image prop
like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_I_promise_I_will_never_shelve_offload=True&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vtpm_is_totally_ephemeral=True&lt;/span&gt;&lt;/code&gt; which would either error or simply not
back up the vTPM, respectively, on shelve-offload.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetaProps&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ImageMetaPropsPayload&lt;/span&gt;&lt;/code&gt; objects need new versions
adding:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_version&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_tpm_model&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_object_id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpm_object_sha256&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The image/flavor validator will get new checks for consistency of properties.
No new microversion is needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The guest will be able to use the emulated TPM for all the security enhancing
functionality that a physical TPM provides, in order to protect itself against
attacks from within the guest.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference internal" href="#key-manager"&gt;key manager&lt;/a&gt; and &lt;a class="reference internal" href="#object-store"&gt;object store&lt;/a&gt; services are assumed to be adequately
hardened against external attack. However, the deployment must consider the
issue of authorized access to these services, as discussed below.&lt;/p&gt;
&lt;section id="data-theft"&gt;
&lt;h4&gt;Data theft&lt;/h4&gt;
&lt;p&gt;The vTPM data file is encrypted on disk, and is therefore “safe” (within the
bounds of encryption) from simple data theft.&lt;/p&gt;
&lt;p&gt;We will use a passphrase of 384 bytes, which is the default size of an SSH key,
generated from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/dev/urandom&lt;/span&gt;&lt;/code&gt;. It may be desirable to make this size
configurable in the future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="compromised-root"&gt;
&lt;h4&gt;Compromised root&lt;/h4&gt;
&lt;p&gt;It is assumed that the root user on the compute node would be able to glean
(e.g. by inspecting memory) the vTPM’s contents and/or the passphrase while
it’s in flight. Beyond using private+ephemeral secrets in libvirt, no further
attempt is made to guard against a compromised root user.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="object-store"&gt;
&lt;h4&gt;Object store&lt;/h4&gt;
&lt;p&gt;The object store service allows full access to an object by the admin user,
regardless of who created the object. There is currently no facility for
restricting admins to e.g. only deleting objects. Thus, if a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shelve&lt;/span&gt;&lt;/code&gt; has
been performed, the contents of the vTPM device will be available to the admin.
They are encrypted, so without access to the key, we are still trusting the
strength of the encryption to protect the data.  However, this increases the
attack surface, assuming the object store admin is different from whoever has
access to the original file on the compute host.&lt;/p&gt;
&lt;p&gt;By the same token (heh) if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shelve&lt;/span&gt;&lt;/code&gt; is performed by the admin, the vTPM data
object will be created and owned by the admin, and therefore only the admin
will be able to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;unshelve&lt;/span&gt;&lt;/code&gt; that instance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="key-manager"&gt;
&lt;h4&gt;Key manager&lt;/h4&gt;
&lt;p&gt;The secret stored in the key manager is more delicate, since it can be used to
decrypt the contents of the vTPM device. The barbican implementation scopes
access to secrets at the project level, so the deployment must take care to
limit the project to users who should all be trusted with a common set of
secrets. Also note that project-scoped admins are by default allowed to access
and decrypt secrets owned by any project; if the admin is not to be trusted,
this should be restricted via policy.&lt;/p&gt;
&lt;p&gt;However, castellan backends are responsible for their own authentication
mechanisms. Thus, the deployment may wish to use a backend that scopes
decryption to only the individual user who created the secret. (In any case it
is important that admins be allowed to delete secrets so that operations such
as VM deletion can be performed by admins without leaving secrets behind.)&lt;/p&gt;
&lt;p&gt;Note that, if the admin is restricted from decrypting secrets, lifecycle
operations performed by the admin cannot result in a running VM. This includes
rebooting the host: even with &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/config.html#DEFAULT.resume_guests_state_on_host_boot"&gt;resume_guests_state_on_host_boot&lt;/a&gt; set, an
instance with a vTPM will not boot automatically, and will instead have to be
powered on manually by its owner.  Other lifecycle operations which are by
default admin-only will only work when performed by the VM owner, meaning the
owner must be given the appropriate policy roles to do so; otherwise these
operations will be in effect disabled.&lt;/p&gt;
&lt;p&gt;…except live migration, since the (already decrypted) running state of the
vTPM is carried along to the destination. (To clarify: live migration, unlike
other operations, would actually work if performed by the admin because of the
above.)&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An additional API call to the key manager is needed during spawn (to register
the passphrase), cold boot (to retrieve it), and destroy (to remove it).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additional API calls to libvirt are needed during spawn and other boot-like
operations to define, set the value, and undefine the vTPM’s secret in
libvirt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additional API calls to the object store (swift) are needed to create
(during shelve), retrieve (unshelve), and delete (unshelve/destroy) the vTPM
device data object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The various virt drivers would be able to implement the emulated vTPM as
desired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfin&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cfriesen
efried&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;stephenfin&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API changes to prevalidate the flavor and image properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler changes to translate flavor/image properties to placement-isms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt driver changes to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;detect &lt;a class="reference internal" href="#prerequisites"&gt;Prerequisites&lt;/a&gt; and &lt;a class="reference internal" href="#config"&gt;Config&lt;/a&gt; and report traits to placement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;communicate with the key manager API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;manage libvirt secrets via the libvirt API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;translate flavor/image properties to domain &lt;a class="reference internal" href="#xml"&gt;XML&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;copy vTPM files on relevant &lt;a class="reference internal" href="#instance-lifecycle-operations"&gt;Instance Lifecycle Operations&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;communicate with object store to save/restore the vTPM files on (other)
relevant &lt;a class="reference internal" href="#instance-lifecycle-operations"&gt;Instance Lifecycle Operations&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="#testing"&gt;Testing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional testing will be added. New fixtures for object store and
key manager services will likely be necessary.&lt;/p&gt;
&lt;p&gt;Because of the eccentricities of a) user authentication for accessing the
encryption secret, and b) management of the virtual device files for some
operations, CI coverage will be added for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Live migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cold migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Host reboot (how?)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shelve (offload) and unshelve&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backup and rebuild&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operations Guide and End User Guide will be updated appropriately.
Feature support matrix will be updated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;TPM on Wikipedia: &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Trusted_Platform_Module"&gt;https://en.wikipedia.org/wiki/Trusted_Platform_Module&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swtpm&lt;/span&gt;&lt;/code&gt;: &lt;a class="reference external" href="https://github.com/stefanberger/swtpm/wiki"&gt;https://github.com/stefanberger/swtpm/wiki&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Qemu docs on tpm:
&lt;a class="reference external" href="https://github.com/qemu/qemu/blob/master/docs/specs/tpm.txt"&gt;https://github.com/qemu/qemu/blob/master/docs/specs/tpm.txt&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt XML to request emulated TPM device:
&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsTpm"&gt;https://libvirt.org/formatdomain.html#elementsTpm&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed with refinements including encryption pieces&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Sep 2020 00:00:00 </pubDate></item><item><title>Allow Nova to download Glance images directly via RBD</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/nova-image-download-via-rbd.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-image-download-via-rbd"&gt;https://blueprints.launchpad.net/nova/+spec/nova-image-download-via-rbd&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When using compute-local storage with qcow2 based VM root disks, Glance images
are downloaded into the libvirt image store by way of the Glance HTTP API.
For images in the 10s-100s of GB, this download can be _very_ slow.
If the compute node has access to Ceph, it can instead perform an ‘rbd export’
on the Glance image, bypassing the Glance API entirely and directly download
the image from Ceph. This direct download can result in a drastic reduction
in download time, from tens of minutes to tens of seconds.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a user with a Ceph-backed image storage, I want to configure some compute
hosts for qcow2 images local to the compute host but quickly get the images
from Ceph rather than slow downloads from the Glance API.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;A special download handler will be registered for Glance images when the ‘rbd’
value is present in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allowed_direct_url_schemes&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;This download handler will be called only when a VM is scheduled on a node and
the required Glance image is not already present in the local libvirt image
cache. It will execute the OS native ‘rbd export’ command, using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;privsep&lt;/span&gt;&lt;/code&gt;,
in order to perform the download operation instead of using the Glance HTTP
API.&lt;/p&gt;
&lt;p&gt;The mechanism for per-scheme download handlers was previously available
as a plugin point, which is now deprecated, along with the
allowed_direct_url_schemes config option. This effort will close out on that
deprecation by moving the per-scheme support into the nova.images.glance module
itself, undeprecating the allowed_direct_url_schemes config, and removing the
old nova.images.download plug point.&lt;/p&gt;
&lt;p&gt;The glance module also never used to perform image signature verification when
the per-scheme module was used. Since we are moving this into core code,
we will also fix this so that per-scheme images are verified like all the rest.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;VM root disks can be run directly within Ceph as creation of these VM root
disks are fast as they are COW clones for the Glance image, also in Ceph.
However, running the VM root disks from Ceph introduces additional latency to
the running VM and needlessly wastes network bandwidth and Ceph IOPS. This
specific functionality was added in Mitaka but is aimed at a different use case
where the VM root disks remain in Ceph and are not run as qcow2 local disks.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/rbd-instance-snapshots.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/rbd-instance-snapshots.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The other alternative is to continue with existing approach only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As proposed, there are no new configuration items, simply configuration of
existing items.&lt;/p&gt;
&lt;p&gt;The following configuration options are required to ensure qcow2 local images
are downloaded from Ceph and cached on the local compute host:&lt;/p&gt;
&lt;p&gt;On the Glance API node in glance-api.conf:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEFAULT.show_image_direct_url=true&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;On the Nova compute node in nova.conf:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEFAULT.force_raw_images=false&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt.images_type=qcow2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt.images_rbd_ceph_conf=&amp;lt;ceph_config_file&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt.rbd_user=&amp;lt;ceph_user_name&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance.allowed_direct_url_schemes&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;rbd&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Looking ahead, it may be desired to create additional entries in the libvirt
section of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt; for this feature as the current implementation assumes
that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_user&lt;/span&gt;&lt;/code&gt; will have access to the Glance images. This may not be
the case depending upon how the Ceph pool permissions are configured.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allowed_direct_url_schemes&lt;/span&gt;&lt;/code&gt; option was deprecated in Queens. Proposed
implementation of this feature would halt the deprecation of this option and
we would need to “un-deprecate” it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Jiri Suchomel &amp;lt;&lt;a class="reference external" href="mailto:jiri.suchomel%40suse.com"&gt;jiri&lt;span&gt;.&lt;/span&gt;suchomel&lt;span&gt;@&lt;/span&gt;suse&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Dan Smith (danms)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Refactor existing in-house out-of-tree implementation and integrate it fully
into current codebase&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write tests for implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the admin guide with the description of how to set up the config if
the new feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an experimental on-demand queue job which uses Ceph with local qcow2
images and ‘direct from rbd’ feature enabled&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The admin guide should be updated to call out this use case and how it differs
from the Ceph-native snapshot feature.  A good place to document this may be:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/configuration/hypervisor-kvm.html#configure-compute-backing-storage"&gt;https://docs.openstack.org/nova/latest/admin/configuration/hypervisor-kvm.html#configure-compute-backing-storage&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-May/131002.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2018-May/131002.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-operators/2018-June/015384.html"&gt;http://lists.openstack.org/pipermail/openstack-operators/2018-June/015384.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Sep 2020 00:00:00 </pubDate></item><item><title>Provider Configuration File</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/provider-config-file.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/provider-config-file"&gt;https://blueprints.launchpad.net/nova/+spec/provider-config-file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a proposal to configure resource provider inventory and traits using a
standardized YAML file format.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is derived from &lt;a class="reference external" href="https://review.openstack.org/#/c/550244/2/specs/rocky/approved/provider-config-file.rst"&gt;Jay’s Rocky provider-config-file
proposal&lt;/a&gt; and &lt;a class="reference external" href="https://review.openstack.org/#/c/591037/8/specs/stein/approved/device-placement-model.rst"&gt;Konstantinos’s device-placement-model spec&lt;/a&gt; (which
is derived from &lt;a class="reference external" href="https://review.openstack.org/#/c/579359/10/doc/source/specs/rocky/device-passthrough.rst"&gt;Eric’s device-passthrough spec&lt;/a&gt;), but differs in
several substantive ways.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is influenced by requirements to Nova to support non
native compute resources that are managed by Resource Management
Daemon for finer grain control. PTG discussion notes available at
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005809.html"&gt;Resource Management Daemon_PTG Summary&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We currently limit the ownership and consumption of the provider
config YAML as described by the file format to Nova only.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The provider config will currently only accept placement overrides
to create and manage inventories and traits for resources not
natively managed by the Nova virt driver.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This is intended to define a) a file format for currently active use
cases, and b) Nova’s consumption of such files. Subsequent features
can define the semantics by which the framework can be used by other
consumers or enhanced to satisfy particular use cases.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In order to facilitate the proper management of resource provider information
in the placement API by agents within Nova (such as virt drivers and the
PCI passthrough subsystem), we require a way of expressing various
overrides for resource provider information. While we could continue to use
many existing and new configuration options for expressing this information,
having a standardized, versioned provider descriptor file format allows us to
decouple the management of provider information from the configuration of the
service or daemon that manages those resource providers.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Note that the file format/schema defined here is designed to accommodate the
following use cases. The file format/schema currently addresses a few use cases
that require changes to resource provider information as consumed by virt
drivers in Nova but it should allow options for extensions to be consumed
by Nova or other services as described in the problem statement in the future.&lt;/p&gt;
&lt;section id="inventory-customization"&gt;
&lt;h4&gt;Inventory Customization&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;An operator would like to describe inventories for new platform features&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These features could be experimental or not yet completely supported by Nova.
The expectation is that Nova can manage these inventories and help schedule
workloads requesting support for new platform features against their
capacities. For instance, to report &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_LLC&lt;/span&gt;&lt;/code&gt; (last-level cache)
inventories.&lt;/p&gt;
&lt;p&gt;The file defined by this spec must allow its author to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Identify a provider unambiguously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create and manage inventories for resource classes not natively managed by
Nova virt driver (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_LLC&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_MEMORY_BANDWIDTH&lt;/span&gt;&lt;/code&gt; etc.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="trait-customization"&gt;
&lt;h4&gt;Trait Customization&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;An operator wishes to associate new custom traits with a provider.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These features could be experimental or not yet completely supported by Nova.
The expectation is that Nova can manage these traits and help schedule
workloads with support to new platform features against their traits.&lt;/p&gt;
&lt;p&gt;The file defined by this spec must allow its author to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Identify a provider unambiguously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify arbitrary custom traits which are to be associated with the provider.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="provider-config-file-schema"&gt;
&lt;h3&gt;Provider Config File Schema&lt;/h3&gt;
&lt;p&gt;A versioned YAML file format with a formal schema is proposed. The scope of
this spec is the schema, code to parse a file into a Python dict, code to
validate the dict against the schema, and code to merge the resulting dict with
the provider tree as processed by the resource tracker.&lt;/p&gt;
&lt;p&gt;The code shall be introduced into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack/nova&lt;/span&gt;&lt;/code&gt; project initially and
consumed by the resource tracker. Parts of it (such as the schema definition,
file loading, and validation) may be moved to a separate oslo-ish library in
the future if it can be standardized for consumption outside of Nova.&lt;/p&gt;
&lt;p&gt;The following is a simplified pseudo-schema for the file format.&lt;/p&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Version ($Major, $minor) of the schema must successfully parse documents&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# conforming to ($Major, *). I.e. additionalProperties must be allowed at&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# all levels; but code at a lower $minor will ignore fields it does not&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# recognize. Schema changes representing optional additions should bump&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# $minor. Any breaking schema change (e.g. removing fields, adding new&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# required fields, imposing a stricter pattern on a value, etc.) must bump&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# $Major. The question of whether/how old versions will be deprecated or&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# become unsupported is left for future consideration.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;schema_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$Major.$minor&lt;/span&gt;

&lt;span class="nt"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# List of dicts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Identify a single provider to configure.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Exactly one of uuid or name is mandatory. Specifying both is an error.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# The consuming nova-compute service will error and fail to start if the&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# same value is used more than once across all provider configs for name&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# or uuid.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# NOTE: Caution should be exercised when identifying ironic nodes,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# especially via the `$COMPUTE_NODE` special value. If an ironic node&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# moves to a different compute host with a different provider config, its&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# attributes will change accordingly.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;identification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Name or UUID of the provider.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# The uuid can be set to the specialized string `$COMPUTE_NODE` which&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# will cause the consuming compute service to apply the configuration&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# in this section to each node it manages unless that node is also&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# identified by name or uuid.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;($uuid_pattern|"$COMPUTE_NODE")&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Name of the provider.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$string&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Customize provider inventories&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;inventories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# This section allows the admin to specify various adjectives to&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# create and manage providers' inventories.  This list of adjectives&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# can be extended in the future as the schema evolves to meet new&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# use cases. For now, only one adjective, `additional`, is supported.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# The following inventories should be created on the identified&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# provider. Only CUSTOM_* resource classes are permitted.&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# Specifying inventory of a resource class natively managed by&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# nova-compute will cause the compute service to fail.&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;$resource_class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# `total` is required. Other optional fields not specified&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# get defaults from the Placement service.&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;min_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;max_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;step_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$int&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;allocation_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$float&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# Next inventory dict, keyed by resource class...&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Customize provider traits.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;traits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# This section allows the admin to specify various adjectives to&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# create and manage providers' traits.  This list of adjectives&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# can be extended in the future as the schema evolves to meet new&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# use cases. For now, only one adjective, `additional`, is supported.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# The following traits are added on the identified provider. Only&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# CUSTOM_* traits are permitted. The consuming code is&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# responsible for ensuring the existence of these traits in&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# Placement.&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$trait_pattern&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Next provider...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;identification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="example"&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This section is intended to describe at a very high level how this
file format could be consumed to provide &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_LLC&lt;/span&gt;&lt;/code&gt; inventory
information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This section is intended to describe at a very high level how this
file format could be consumed to provide P-state compute trait
information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-yaml notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nt"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;schema_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1.0&lt;/span&gt;

&lt;span class="nt"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# List of dicts&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;identification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;$COMPUTE_NODE&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;inventories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;CUSTOM_LLC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# Describing LLC on this compute node&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# max_unit indicates maximum size of single LLC&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# total indicates sum of sizes of all LLC&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;22&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;min_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;max_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;11&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;step_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;allocation_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;traits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# Describing that this compute node enables support for&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# P-state control&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;CUSTOM_P_STATE_ENABLED&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="provider-config-consumption-from-nova"&gt;
&lt;h3&gt;Provider config consumption from Nova&lt;/h3&gt;
&lt;p&gt;Provider config processing will be performed by the nova-compute process as
described below. There are no changes to virt drivers. In particular, virt
drivers have no control over the loading, parsing, validation, or integration
of provider configs. Such control may be added in the future if warranted.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Configuration&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A new config option is introduced:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;[compute]
# Directory of yaml files containing resource provider configuration.
# Default: /etc/nova/provider_config/
# Files in this directory will be processed in lexicographic order.
provider_config_location = $directory
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;dt&gt;Loading, Parsing, Validation&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;On nova-compute startup, files in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.compute.provider_config_location&lt;/span&gt;&lt;/code&gt;
are loaded and parsed by standard libraries (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;yaml&lt;/span&gt;&lt;/code&gt;), and
schema-validated (e.g. via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;jsonschema&lt;/span&gt;&lt;/code&gt;). Schema validation failure or
multiple identifications of a node will cause nova-compute startup to fail.
Upon successful loading and validation, the resulting data structure is
stored in an instance attribute on the ResourceTracker.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Provider Tree Merging&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A generic (non-hypervisor/virt-specific) method will be written that merges
the provider config data into an existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ProviderTree&lt;/span&gt;&lt;/code&gt; data structure.
The method must detect conflicts whereby provider config data references
inventory of a resource class managed by the virt driver. Conflicts should
log a warning and cause the conflicting config inventory to be ignored.
The exact location and signature of this method, as well as how it detects
conflicts, is left to the implementation. In the event that a resource
provider is identified by both explicit UUID/NAME and $COMPUTE_NODE, only the
UUID/NAME record will be used.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_update_to_placement&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;In the ResourceTracker’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_update_to_placement&lt;/span&gt;&lt;/code&gt; flow, the merging method is
invoked after &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree&lt;/span&gt;&lt;/code&gt; and automatic trait processing, &lt;em&gt;only&lt;/em&gt;
in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree&lt;/span&gt;&lt;/code&gt; flow (not in the legacy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_inventory&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_node_to_inventory_dict&lt;/span&gt;&lt;/code&gt; flows). On startup (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;startup&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;),
if the merge detects a conflict, the nova-compute service will fail.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Ad hoc provider configuration is being performed today through an amalgam of
oslo.config options, more of which are being proposed or considered to deal
with VGPUs, NUMA, bandwidth resources, etc. The awkwardness of expressing
hierarchical data structures has led to such travesties as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[pci]passthrough_whitelist&lt;/span&gt;&lt;/code&gt; and “dynamic config” mechanisms where config
groups and their options are created on the fly. YAML is natively suited for
this purpose as it is designed to express arbitrarily nested data structures
clearly, with minimal noisy punctuation. In addition, the schema is
self-documenting.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Admins should ensure that provider config files have appropriate permissions
and ownership. Consuming services may wish to check this and generate an error
if a file is writable by anyone other than the process owner.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;An understanding of this file and its implications is only required when the
operator desires provider customization. The deployer should be aware of the
precedence of records with UUID/NAME identification over $COMPUTE_NODE.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Subsequent specs will be needed for services consuming this file format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None. (Consumers of this file format will need to address this - e.g. decide
how to deprecate existing config options which are being replaced).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;tony su&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dustinc
efried dakshinai&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gibi&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Construct a formal schema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement parsing and schema validation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement merging of config to provider tree&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incorporate above into ResourceTracker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compose a self-documenting sample file&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Schema validation will be unit tested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional and integration testing to move updates from provider config file
to Placement via Nova virt driver.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The formal schema file and a self-documenting sample file for provider
config file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Admin-facing documentation on guide to update the file and how Nova
processes the updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User-facing documentation (including release notes).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed, simplified&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Sep 2020 00:00:00 </pubDate></item><item><title>Libvirt RBD image backend support for glance multistore</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/rbd-glance-multistore.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/rbd-glance-multistore"&gt;https://blueprints.launchpad.net/nova/+spec/rbd-glance-multistore&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, Nova does not natively support a deployment where there are
multiple Ceph RBD backends that are known to glance. If there is only
one, Nova and Glance collaborate for fast-and-light image-to-VM
cloning behaviors. If there is more than one, Nova generally does not
handle the situation well, resulting in silent slow-and-heavy behavior
in the worst case, and a failed instance boot failsafe condition in
the best case. We can do better.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are certain situations where it is desirable to have multiple
independent Ceph clusters in a single openstack deployment. The most
common would be a multi-site or edge deployment where it is important
that the Ceph cluster is physically close to the compute nodes that it
serves. Glance already has the ability to address multiple ceph
clusters, but Nova is so naive about this that such a configuration
will result in highly undesirable behavior.&lt;/p&gt;
&lt;p&gt;Normally when Glance and Nova collaborate on a single Ceph deployment,
images are stored in Ceph by Glance when uploaded by the operator or
the user. When Nova starts to boot an instance, it asks Ceph to make a
Copy-on-Write clone of that image, which extremely fast and
efficient, resulting in not only reduced time to boot and lower
network traffic, but a shared base image across all compute nodes.&lt;/p&gt;
&lt;p&gt;If, on the other hand, you have two groups of compute nodes, each with
their own Ceph deployment, extreme care must be taken currently to
ensure that an image stored in one is not booted on a compute node
assigned to the other. Glance can represent that a single logical
image is stored in one or both of those Ceph stores and Nova looks at
this during instance boot. However, if the image is not in its local
Ceph cluster, it will quietly download the image from Glance and then
upload it to its local Ceph as a raw flat image each time an instance
from that image is booted. This results in more network traffic and
disk usage than is expected. We merged a workaround to make Nova
refuse to do this antithetical behavior, but it just causes a failed
instance boot.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator I want to be able to have a multi-site single Nova
deployment with one Ceph cluster per site and retain the
high-performance copy-on-write behavior that I get with a single
one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a power user which currently has to pre-copy images to a
remote-site ceph backend with glance before being able to boot an
instance, I want to not have to worry about such things and just
have Nova do that for me.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Glance can already represent that a single logical image is stored in
multiple locations. Recently, it gained an API to facilitate copying
images between backend stores. This means that an API consumer can
request that it copy an image from one store to another by doing an
“import” operation where the method is “copy-image”.&lt;/p&gt;
&lt;p&gt;The change proposed in this spec is to augment the existing libvirt
RBD imagebackend code so that it can use this image copying API when
needed. Currently, we already look at all the image locations to find
which one matches our Ceph cluster, and then use that to do the
clone. After this spec is implemented, that code will still examine
all the &lt;em&gt;current&lt;/em&gt; locations, and if none match, ask Glance to copy the
image to the appropriate backend store so we can continue without
failure or other undesirable behavior.&lt;/p&gt;
&lt;p&gt;In the case where we do need Glance to copy the image to our store,
Nova can monitor the progress of the operation through special image
properties that Glance maintains on the image. These indicate that the
process is in-progress (via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_glance_importing_to_stores&lt;/span&gt;&lt;/code&gt;) and
also provide notice when an import has failed (via
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_glance_failed_import&lt;/span&gt;&lt;/code&gt;). Nova will need to poll the image,
waiting for the process to complete, and some configuration knobs will
be needed to allow for appropriate tuning.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative is always to do nothing. This is enhanced behavior on
top of what we already support. We &lt;em&gt;could&lt;/em&gt; just tell people not to use
multiple Ceph deployments or add further checks to make sure we do not
do something stupid if they do.&lt;/p&gt;
&lt;p&gt;We could teach nova about multiple RBD stores in a more comprehensive
way, which would basically require either pulling ceph information out
of Glance, or configuring Nova with all the same RBD backends that
Glance has. However, we would need to teach Nova about the topology
and configure it to not do stupid things like use a remote Ceph just
because the image is there.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Users can already use the image import mechanism in Glance, so Nova
using it on their behalf does not result in privilege escalation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This removes the need for users to know details about the deployment
configuration and topology, as well as eliminates the need to manually
pre-place images in stores.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Image boot time will be impacted in the case when a copy needs to
happen, of course. Performance overall will be much better because
operators will be able to utilize more Ceph clusters if they wish,
and locate them closer to the compute nodes they serve.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Some additional configuration will be needed in order to make this
work. Specifically, Nova will need to know the Glance store name that
represents the RBD backend it is configured to use. Additionally,
there will be some timeout tunables related to how often we poll the
Glance server for status on the copy, as well as an overall timeout
for how long we are willing to wait.&lt;/p&gt;
&lt;p&gt;One other deployer consideration is that Glance requires an API setup
capable of doing background tasks in order to support the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_import&lt;/span&gt;&lt;/code&gt; API. That means &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mod_wsgi&lt;/span&gt;&lt;/code&gt; or similar, as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uwsgi&lt;/span&gt;&lt;/code&gt;
does not provide reliable background task support. This is just a
Glance requirement, but worth noting here.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The actual impact to the imagebackend code is not large as we are just
using a new mechanism in Glance’s API to do the complex work of
copying images between backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;In order to utilize this new functionality, at least Glance from
Ussuri will be required for a Victoria Nova. Individual
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; services can utilize this new functionality
immediately during a partial upgrade scenario so no minimum service
version checks are required. The control plane does not know which RBD
backend each compute node is connected to, and thus there is no need
for control-plane-level upgrade sensitivity to this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Plumb the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_import&lt;/span&gt;&lt;/code&gt; function through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.image.glance&lt;/span&gt;&lt;/code&gt; modules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Teach the libvirt RBD imagebackend module how to use the new API to
copy images to its own backend when necessary and appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document the proper setup requirements for administrators&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance requirements are already landed and available&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit testing, obviously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional testing turns out to be quite difficult, as we stub out
massive amounts of the underlying image handling code underneath our
fake libvirt implementation. Adding functional tests for this would
require substantial refactoring of all that test infrastructure,
dwarfing the actual code in this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Devstack testing turns out to be relatively easy. I think we can get
a solid test of this feature on every run, by altering that job to:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enable Glance and Nova multistore support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable Glance image conversion support, to auto-convert the default
QCOW Cirros image to raw when we upload it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create two stores, one file-backed (like other jobs) and one
RBD-backed (like the current Ceph job).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Default the Cirros upload to the file-backed store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first use of the Cirros image in a tempest test will cause Nova
to ask Glance to copy the image from the file-backed store to the
RBD-backed store. Subsequent tests will see it as already in the
RBD store and proceed as normal.&lt;/p&gt;
&lt;p&gt;The real-world goal of this is to facilitate RBD-to-RBD backend
store copying, but from Nova’s perspective file-to-RBD is an
identical process, so it’s a good analog without having to
bootstrap two independent Ceph clusters in a devstack job.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This is largely admin-focused. Users that are currently aware of this
limitation already have admin-level knowledge if they are working
around it. Successful implementation will just eliminate the need to
care about multiple Ceph deployments going forward. Thus admin and
configuration documentation should be sufficient.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/copy-existing-image"&gt;https://blueprints.launchpad.net/glance/+spec/copy-existing-image&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/glance/latest/admin/interoperable-image-import.html"&gt;https://docs.openstack.org/glance/latest/admin/interoperable-image-import.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/699656/8"&gt;https://review.opendev.org/#/c/699656/8&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Sep 2020 00:00:00 </pubDate></item><item><title>Support SRIOV interface attach and detach</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/sriov-interface-attach-detach.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/sriov-interface-attach-detach"&gt;https://blueprints.launchpad.net/nova/+spec/sriov-interface-attach-detach&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova supports booting servers with SRIOV interfaces. However, attaching and
detaching an SRIOV interface to an existing server is not supported as the PCI
device management is missing from the attach and detach code path.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;SRIOV interfaces cannot be attached or detached from an existing nova server.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an end user I need to connect my server to another neutron network via an
SRIOV interface to get high throughput connectivity to that network direction.&lt;/p&gt;
&lt;p&gt;As an end user I want to detach an existing SRIOV interface as I don’t use that
network access anymore and I want to free up the scarce SRIOV resource.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In the compute manager, during interface attach, the compute needs to generate
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstancePCIRequest&lt;/span&gt;&lt;/code&gt; for the requested port if the vnic_type of the port
indicates an SRIOV interface. Then run a PCI claim on the generated PCI request
to check if there is a free PCI device, claim it, and get a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PciDevice&lt;/span&gt;&lt;/code&gt;
object. If this is successful then connect the PCI request to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestedNetwork&lt;/span&gt;&lt;/code&gt; object and call Neutron as today with that
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestedNetwork&lt;/span&gt;&lt;/code&gt;. Then call the virt driver as of today.&lt;/p&gt;
&lt;p&gt;If the PCI claim fails then the interface attach instance action will fail but
the instance state will not be set to ERROR.&lt;/p&gt;
&lt;p&gt;During detach, we have to recover the PCI request from the VIF being destroyed
then from that, we can get the PCI device that we need to unclaim in the PCI
tracker.&lt;/p&gt;
&lt;p&gt;Note that detaching an SRIOV interface succeeds today from API user
perspective. However, the detached PCI device is not freed from resource
tracking and therefore leaked until the nova server is deleted or live
migrated. This issue will be gone when the current spec is implemented. Also
as a separate bugfix SRIOV detach will be blocked on stable branches to prevent
the resource leak.&lt;/p&gt;
&lt;p&gt;There is a separate issue with SRIOV PF detach due to the way the libvirt
domain XML is generated. While the fix for that is needed for the current spec,
it also needed for the existing SRIOV live migration feature because that also
detaches the SRIOV interfaces during the migration. So the SRIOV PF detach
issue will be fixed as an independent bugfix of the SRIOV live migration
feature and the implementation of this spec will depend on that bugfix.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be an extra neutron call during interface attach as well as
additional DB operations. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;interface_attach&lt;/span&gt;&lt;/code&gt; RPC method is synchronous
today, so this will be an end user visible change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gibi&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;change the attach and detach code path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add unit and functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Tempest test cannot be added since the upstream CI does not have SRIOV devices.
Functional tests with libvirt driver will be added instead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;remove the limitation from the API documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Sep 2020 00:00:00 </pubDate></item><item><title>Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; in One Instance</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/use-pcpu-vcpu-in-one-instance.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/use-pcpu-and-vcpu-in-one-instance"&gt;https://blueprints.launchpad.net/nova/+spec/use-pcpu-and-vcpu-in-one-instance&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec &lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;CPU resource tracking&lt;/a&gt; splits host CPUs into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;
resources, making it possible to run instances of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; CPU allocation
policy and instances of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; CPU allocation policy in the same host.
This spec aims to create such kind of instance that some of the vCPUs are
dedicated (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;) CPUs and the remaining vCPUs are shared (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;) vCPUs
and expose this information via the metadata API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current CPU allocation policy, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;, is applied to
all vCPUs of an instance. However, with the introduction of
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;CPU resource tracking&lt;/a&gt;, it is possible to propose a more fine-grained CPU
allocation policy, which is based on the control over individual instance vCPU,
and specifying the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; CPU allocation policy to each
instance vCPU.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I would like to have an instance with some realtime CPUs for
high performance, and at the same time, in order to increase instance density,
I wish to make the remaining CPUs, which do not demand high performance,
shared with other instances because I only care about the performance of
realtime CPUs. One example is deploying the NFV task that is enhanced with
DPDK framework in the instance, in which the data plane threads could be
processed with the realtime CPUs and the control-plane tasks are scheduled
on CPUs that may be shared with other instances.&lt;/p&gt;
&lt;p&gt;As a Kubernetes administrator, I wish to run a multi-tier or auto-scaling
application in Kubernetes, which is running in single OpenStack VM, with
the expectation that using dedicated high-performance CPUs for application
itself and deploying the containers on shared cores.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="introduce-a-new-cpu-allocation-policy-mixed"&gt;
&lt;h3&gt;Introduce a new CPU allocation policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; are the existing instance CPU allocation policies
that determine how instance CPU is scheduled on host CPU. This specification
proposes a new CPU allocation policy, with the name &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt;, to
create a CPU &lt;em&gt;mixed&lt;/em&gt; instance in such way that some instance vCPUs are
allocated from computing node’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource, and the rest of instance
vCPUs are allocated from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources. The CPU allocated from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource will be pinned on particular host CPUs which are defined in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.compute.dedicated_cpu_set&lt;/span&gt;&lt;/code&gt;, and the CPU from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resource will be
floating on the host CPUs which are defined in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.compute.shared_cpu_set&lt;/span&gt;&lt;/code&gt;.
In this proposal, we call these two kinds of vCPUs as &lt;em&gt;dedicated&lt;/em&gt; vCPU and
&lt;em&gt;shared&lt;/em&gt; vCPU respectively.&lt;/p&gt;
&lt;section id="instance-cpu-policy-matrix"&gt;
&lt;h4&gt;Instance CPU policy matrix&lt;/h4&gt;
&lt;p&gt;Nova operator may set the instance CPU allocation policy through the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_policy&lt;/span&gt;&lt;/code&gt; interfaces, which may raise conflict.
The CPU policy conflict is proposed to be solved with the following policy
matrix:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td colspan="2" rowspan="2"&gt;&lt;p&gt;INSTANCE CPU POLICY&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="4"&gt;&lt;p&gt;hw:cpu_policy&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;DEDICATED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;MIXED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;SHARED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;undefined&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td rowspan="4"&gt;&lt;p&gt;hw_cpu_policy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;DEDICATED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;dedicated&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;conflict&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;conflict&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;dedicated&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;MIXED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;dedicated&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;mixed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;conflict&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;mixed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;SHARED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;dedicated&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;conflict&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;shared&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;shared&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;undefined&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;dedicated&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;mixed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;shared&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;undefined&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For example, if a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; CPU policy is specified in instance flavor
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt;, then the instance CPU policy is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt;, regardless
of the setting specified in image property &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_policy&lt;/span&gt;&lt;/code&gt;. If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;
is explicitly set in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt;, then a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; policy specified
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_policy&lt;/span&gt;&lt;/code&gt; is conflict, which will throw an exception, the instance
booting request will be rejected.&lt;/p&gt;
&lt;p&gt;If there is no explicit instance CPU policy specified in flavor or image
property, the flavor matrix result would be ‘undefined’, and the final
instance policy is further determined and resolved by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:PCPU&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:VCPU&lt;/span&gt;&lt;/code&gt; specified in flavor extra specs. Refer to
&lt;a class="reference internal" href="#mixed-instance-pcpu-vcpu"&gt;&lt;span class="std std-ref"&gt;section&lt;/span&gt;&lt;/a&gt; and the spec
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;CPU resource tracking&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="affect-over-real-time-vcpus"&gt;
&lt;h4&gt;Affect over real-time vCPUs&lt;/h4&gt;
&lt;p&gt;Real-time vCPU also occupies the host CPU exclusively and does not share CPU
with other instances, all real-time vCPUs are dedicated vCPUs. For a &lt;em&gt;mixed&lt;/em&gt;
instance with some real-time vCPUs, with this proposal, the vCPUs not in the
instance real-time vCPU list are shared vCPUs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="affect-over-emulator-thread-policy"&gt;
&lt;h4&gt;Affect over emulator thread policy&lt;/h4&gt;
&lt;p&gt;If emulator thread policy is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ISOLATE&lt;/span&gt;&lt;/code&gt;, the &lt;em&gt;mixed&lt;/em&gt; instance will look for
a &lt;em&gt;dedicated&lt;/em&gt; host CPU for instance emulator thread, which is very similar
to the case introduced by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; policy instance.&lt;/p&gt;
&lt;p&gt;If the emulator thread policy is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHARE&lt;/span&gt;&lt;/code&gt;, then the instance emulator thread
will float over the host CPUs defined in configuration
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.compute.cpu_shared_set&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="set-dedicated-cpu-bit-mask-in-hw-cpu-dedicated-mask-for-mixed-instance"&gt;
&lt;h3&gt;Set dedicated CPU bit-mask in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt; for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; instance&lt;/h3&gt;
&lt;p&gt;As an interface to create the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; policy instance through legacy flavor
extra specs or image properties, the flavor extra spec
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt; is introduced. If the extra spec
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt; is found in the instance flavor, then the
information of the &lt;em&gt;dedicated&lt;/em&gt; CPU could be found through
parsing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is the example to create an instance with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; policy:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor set &amp;lt;flavor_id&amp;gt; \
    --property hw:cpu_policy=mixed \
    --property hw:cpu_dedicated_mask=0-3,7
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And, following is the proposing command to create a &lt;em&gt;mixed&lt;/em&gt; instance which
consists of multiple NUMA nodes by setting the &lt;em&gt;dedicated&lt;/em&gt; vCPUs in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor set &amp;lt;flavor_id&amp;gt; \
    --property hw:cpu_policy=mixed \
    --property hw:cpu_dedicated_mask=2,7 \
    --property hw:numa_nodes=2 \
    --property hw:numa_cpus.0=0-2 \
    --property hw:numa_cpus.1=3-7 \
    --property hw:numa_mem.0=1024 \
    --property hw:numa_mem.1=2048
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Please be aware that there is no equivalent setting in image properties
for flavor extra spec &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt;. It will not be supported
to create &lt;em&gt;mixed&lt;/em&gt; instance through image properties.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The dedicated vCPU list of a &lt;em&gt;mixed&lt;/em&gt; instance could be specified through
the newly introduced dedicated CPU mask or the cpu-time CPU mask, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_realtime_mask&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_realtime_mask&lt;/span&gt;&lt;/code&gt;, you cannot set it
by setting dedicated CPU mask extra spec and real-time CPU mask at the
same time.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="create-mixed-instance-via-resources-pcpu-and-resources-vcpu"&gt;
&lt;span id="mixed-instance-pcpu-vcpu"/&gt;&lt;h3&gt;Create &lt;em&gt;mixed&lt;/em&gt; instance via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:VCPU&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;CPU resource tracking&lt;/a&gt; introduced a way to create an instance with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; CPU allocation policy through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:PCPU&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:VCPU&lt;/span&gt;&lt;/code&gt; interfaces, but did not allow requesting both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;
resource and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resource for one instance.&lt;/p&gt;
&lt;p&gt;This specification proposes to let an instance request &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource along
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;, and effectively applying for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; CPU allocation
policy if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_policy&lt;/span&gt;&lt;/code&gt; is not explicitly specified in the flavor list.
So an instance with such flavors potentially creates a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; policy
instance:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor set \
    --property "resources:PCPU"="&amp;lt;dedicated CPU number&amp;gt;" \
    --property "resources:VCPU"="&amp;lt;shared CPU number&amp;gt;" \
    &amp;lt;flavor_id&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For &lt;em&gt;mixed&lt;/em&gt; instance created in such way, both &amp;lt;shared CPU number&amp;gt; and
&amp;lt;dedicated CPU number&amp;gt; must be greater than zero. Otherwise, it effectively
creates the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; policy instance, that all vCPUs in the
instance is in a same allocation policy.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources::VCPU&lt;/span&gt;&lt;/code&gt; interfaces only put the request
toward &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Placement&lt;/span&gt;&lt;/code&gt; service for how many &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources are
required to fulfill the instance vCPU thread and emulator thread requirement.
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; distribution on the instance, especially on the
instance with multiple NUMA nodes, will be spread across the NUMA nodes in the
round-robin way, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; will be put ahead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;. Here is one
example and the instance is created with flavor below:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;flavor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;vcpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="n"&gt;memory_mb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;
  &lt;span class="n"&gt;extra_specs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;numa_nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Instance emulator thread policy is not specified in the flavor, so it does not
occupy any dedicated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource for it, all &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;
resources will be used by vCPU threads, and the expected distribution on NUMA
nodes is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt;
&lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The demanding instance CPU number is the number of vCPU, specified by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavor.vcpus&lt;/span&gt;&lt;/code&gt;, plus the number of CPU that is special for emulator
thread, and if the emulator thread policy is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ISOLATE&lt;/span&gt;&lt;/code&gt;, the instance
requests &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavor.vcpus&lt;/span&gt;&lt;/code&gt; + 1 vCPUs, if the policy is not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ISOLATE&lt;/span&gt;&lt;/code&gt;,
the instance just requests &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavor.vcpus&lt;/span&gt;&lt;/code&gt; vCPU.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="creating-cpu-mixed-instance-by-extending-the-dedicated-policy"&gt;
&lt;h4&gt;Creating CPU mixed instance by extending the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; policy&lt;/h4&gt;
&lt;p&gt;Instead of adding a special instance CPU allocation policy, the CPU mixed
instance is supported by extending the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; policy and
specifying the vCPUs that are pinned to the host CPUs chosen from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;
resource.&lt;/p&gt;
&lt;p&gt;Following extra spec and the image property are defined to keep the
&lt;em&gt;dedicated&lt;/em&gt; vCPUs of a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; policy instance:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cpu_dedicated_mask&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;hw_cpu_dedicated_mask&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;cpu&lt;/span&gt; &lt;span class="pre"&gt;set&lt;/span&gt; &lt;span class="pre"&gt;string&amp;gt;&lt;/span&gt;&lt;/code&gt; shares the same definition defined above.&lt;/p&gt;
&lt;p&gt;This was rejected at it overloads the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; policy to mean two things,
depending on the value of another configuration option.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="creating-mixed-instance-with-hw-cpu-policy-and-resources-p-v-cpu"&gt;
&lt;h4&gt;Creating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; instance with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:(P|V)CPU&lt;/span&gt;&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Following commands was proposed as an example to create a &lt;em&gt;mixed&lt;/em&gt; instance by
an explicit request of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources, and infer the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; count by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavor::vcpus&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; count:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create mixed_vmf --vcpus 4 --ram 512 --disk 1
$ openstack flavor set mixed_vmf \
    --property hw:cpu_policy=mixed \
    --property resources:PCPU=2
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This was rejected due to the mixing use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:PCPU&lt;/span&gt;&lt;/code&gt;. It is not recommended to mix placement style syntax with
traditional extra specs.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pcpuset&lt;/span&gt;&lt;/code&gt; field in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell&lt;/span&gt;&lt;/code&gt; object to track the dedicated
vCPUs of the instance NUMA cell, and the original &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell.cpuset&lt;/span&gt;&lt;/code&gt;
is special for shared vCPU then.&lt;/p&gt;
&lt;p&gt;This change will introduce some database migration work for the existing
instance in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; CPU allocation policy, since all vCPUs in such an
instance are dedicated vCPUs which should be kept in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pcpuset&lt;/span&gt;&lt;/code&gt; field, but
they are stored in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpuset&lt;/span&gt;&lt;/code&gt; historically.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The metadata API will be extended with the &lt;em&gt;dedicated&lt;/em&gt; vCPU info and a new
OpenStack metadata version will be added to indicate this is a new metadata
API.&lt;/p&gt;
&lt;p&gt;The new field will be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;meta_data.json&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;dedicated_cpus&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;cpu&lt;/span&gt; &lt;span class="pre"&gt;set&lt;/span&gt; &lt;span class="pre"&gt;string&amp;gt;&lt;/span&gt;&lt;/code&gt; lists the &lt;em&gt;dedicated&lt;/em&gt; vCPU set of the instance, which
might be the content of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_realtime_mask&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_realtime_mask&lt;/span&gt;&lt;/code&gt; or the CPU list
generated with the &lt;em&gt;round-robin&lt;/em&gt; policy as described in
&lt;a class="reference internal" href="#mixed-instance-pcpu-vcpu"&gt;&lt;span class="std std-ref"&gt;section&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The new cpu policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; is added to extra spec &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;If the end user wants to create an instance with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; CPU allocation
policy, the user is required to set corresponding flavor extra specs or image
properties.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This proposal affects the selection of instance CPU allocation policy, but the
performance impact is trivial.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; cpu policy is only available when the whole cluster upgrade
finished. A service version will be bumped for detecting the upgrade.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell.pcpuset&lt;/span&gt;&lt;/code&gt; is introduced for dedicated vCPUs and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell.cpuset&lt;/span&gt;&lt;/code&gt; is special for shared vCPUs, all existing
instances in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; CPU allocation policy should be updated by moving
content in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell.cpuset&lt;/span&gt;&lt;/code&gt; filed to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell.pcpuset&lt;/span&gt;&lt;/code&gt; field. The underlying database keeping the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUACell&lt;/span&gt;&lt;/code&gt; object also need be updated to reflect this change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Wang, Huaqiang &amp;lt;&lt;a class="reference external" href="mailto:huaqiang.wang%40intel.com"&gt;huaqiang&lt;span&gt;.&lt;/span&gt;wang&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Stephen Finucane &amp;lt;&lt;a class="reference external" href="mailto:stephenfin%40redhat.com"&gt;stephenfin&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new field, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pcpuset&lt;/span&gt;&lt;/code&gt;, for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMACell&lt;/span&gt;&lt;/code&gt; for dedicated
vCPUs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new instance CPU allocation policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; property and resolve
conflicts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bump nova service version to indicate the new CPU policy in nova-compute&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add flavor extra spec &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_dedicated_mask&lt;/span&gt;&lt;/code&gt; and create &lt;em&gt;mixed&lt;/em&gt; instance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Translate &lt;em&gt;dedicated&lt;/em&gt; and &lt;em&gt;shared&lt;/em&gt; CPU request to placement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change libvirt driver to create &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; mapping and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; mapping&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add nova metadata service by offering final pCPU layout in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated_cpus&lt;/span&gt;&lt;/code&gt; field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate real-time CPU mask for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional and unit tests are required to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ensure to solve the conflicts between the CPU policy matrix&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure only &lt;em&gt;dedicated&lt;/em&gt; vCPUs are possible to be real-time vCPUs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure creating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; policy instance properly either by flavor
settings or by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources::PCPU=xx&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources::VCPU=xx&lt;/span&gt;&lt;/code&gt; settings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure &lt;em&gt;shared&lt;/em&gt; vCPUs is placed before the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; vCPUs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the emulator CPU is properly scheduled according to its policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The documents should be changed to introduce the usage of new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mixed&lt;/span&gt;&lt;/code&gt; CPU
allocation policy and the new flavor extra specs.&lt;/p&gt;
&lt;p&gt;Metadata service will be updated accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;CPU resource tracking&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced, abandoned&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Sep 2020 00:00:00 </pubDate></item><item><title>support virtual persistent memory</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/virtual-persistent-memory.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virtual-persistent-memory"&gt;https://blueprints.launchpad.net/nova/+spec/virtual-persistent-memory&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Virtual persistent memory is now supported in both QEMU and
libvirt. This spec seeks to enable this support in OpenStack Nova.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;For many years computer applications organized their data between
two tiers: memory and storage. Emerging &lt;a class="reference external" href="http://pmem.io/"&gt;persistent memory&lt;/a&gt;
technologies introduce a third tier. Persistent memory
(or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pmem&lt;/span&gt;&lt;/code&gt; for short) is accessed like volatile memory, using processor
load and store instructions, but it retains its contents across power
loss like storage.&lt;/p&gt;
&lt;p&gt;Virtualization layer has already supported virtual persistent memory
which means virtual machines now can have physical persistent memory
as the backend of virtual persistent memory. As far as Nova is concerned,
several problems need to be addressed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;How is the physical persistent memory managed and presented as
virtual persistent memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The discovery and resource tracking of persistent memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does the user specify the desired amount of virtual persistent
memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the life cycle of virtual persistent memory&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Provide applications with the ability to load large contiguous segments
of memory that retain their data across power cycles.&lt;/p&gt;
&lt;p&gt;Besides data persistence, persistent memory is less expensive than DRAM
and comes with much larger capacities. This is an appealing feature for
scenarios that request huge amounts of memory such as high performance
computing (HPC).&lt;/p&gt;
&lt;p&gt;There has been some exploration by applications which heavily use memory
devices such as in memory databases. To name a few: &lt;a class="reference external" href="https://redislabs.com/blog/persistent-memory-and-redis-enterprise/"&gt;redis&lt;/a&gt;, &lt;a class="reference external" href="http://istc-bigdata.org/index.php/nvmrocks-rocksdb-on-non-volatile-memory-systems/"&gt;rocksdb&lt;/a&gt;,
&lt;a class="reference external" href="https://blogs.vmware.com/apps/2018/09/accelerating-oracle-performance-using-vsphere-persistent-memory-pmem.html"&gt;oracle&lt;/a&gt;, &lt;a class="reference external" href="https://blogs.sap.com/2018/12/03/sap-hana-persistent-memory/"&gt;SAP HANA&lt;/a&gt; and &lt;a class="reference external" href="https://www.aerospike.com/resources/videos/aerospike-intel-persistent-memory-2/"&gt;Aerospike&lt;/a&gt;.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec only intends to enable virtual persistent memory
for the libvirt KVM driver.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="background"&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;The most efficient way for an applications to use persistent memory is
to memory map (mmap()) a portion of persistent memory into the address
space of the application. Once the mapping is done, the application
accesses the persistent memory &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;directly&lt;/span&gt;&lt;/code&gt; (also called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt; &lt;span class="pre"&gt;access&lt;/span&gt;&lt;/code&gt;),
meaning without going through kernel or whatever other software in the
middle. Persistent memory has two types of hardware interfaces –
“PMEM” and “BLK”. Since “BLK” adopts an aperture model to access
persistent memory, it does not support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt; &lt;span class="pre"&gt;access&lt;/span&gt;&lt;/code&gt;.
For the sake of efficiency, this spec only proposes to use persistent
memory accessed by “PMEM” interface as the backend for QEMU virtualized
persistent memory.&lt;/p&gt;
&lt;p&gt;Persistent memory must be partitioned into &lt;a class="reference external" href="http://pmem.io/ndctl/ndctl-create-namespace.html"&gt;pmem namespaces&lt;/a&gt; for
applications to use. There are several modes of pmem namespaces for
different use scenarios. Mode &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devdax&lt;/span&gt;&lt;/code&gt; and mode &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fsdax&lt;/span&gt;&lt;/code&gt; both
support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt; &lt;span class="pre"&gt;access&lt;/span&gt;&lt;/code&gt;. Mode &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devdax&lt;/span&gt;&lt;/code&gt; gives out a character
device for a namespace, thus applications can mmap() the entire
namespace into their address spaces. Whereas mode &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fsdax&lt;/span&gt;&lt;/code&gt; gives
out a block device. It is recommended to use mode &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devdax&lt;/span&gt;&lt;/code&gt; to
assign persistent memory to virtual machines.
Please refer to &lt;a class="reference external" href="https://github.com/qemu/qemu/blob/19b599f7664b2ebfd0f405fb79c14dd241557452/docs/nvdimm.txt#L145"&gt;virtual NVDIMM backends&lt;/a&gt; and
&lt;a class="reference external" href="https://www.kernel.org/doc/Documentation/nvdimm/nvdimm.txt"&gt;NVDIMM Linux kernel document&lt;/a&gt; for details.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;So this spec only proposes to use persistent memory namespaces in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devdax&lt;/span&gt;&lt;/code&gt; mode as QEMU virtual persistent memory backends.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devdax&lt;/span&gt;&lt;/code&gt; persistent memory namespaces require contiguous physical
space and are not managed in pages as ordinary system memory.
This introduces a fragmentation issue with regard to multiple namespaces
are created and used by multiple applications. As shown in below diagram,
four applications are using four namespaces each of size 100GB:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;  &lt;span class="o"&gt;+-----+&lt;/span&gt;   &lt;span class="o"&gt;+-----+&lt;/span&gt;   &lt;span class="o"&gt;+-----+&lt;/span&gt;    &lt;span class="o"&gt;+-----+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app4&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--+--+&lt;/span&gt;   &lt;span class="o"&gt;+--+--+&lt;/span&gt;   &lt;span class="o"&gt;+--+--+&lt;/span&gt;    &lt;span class="o"&gt;+--+--+&lt;/span&gt;
     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
     &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;----+----&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;----+----&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;----+-----&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;---+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+---------+---------+---------+---------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After the termination of app2 and app4, it turns out to be:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;  &lt;span class="o"&gt;+-----+&lt;/span&gt;             &lt;span class="o"&gt;+-----+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+--+--+&lt;/span&gt;             &lt;span class="o"&gt;+--+--+&lt;/span&gt;
     &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
     &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;----+---------+----&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;----+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+---------+---------+---------+---------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The total size of free space is 200GB. However a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;devdax&lt;/span&gt;&lt;/code&gt; mode
namespace of 200GB size can not be created.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="persistent-memory-namespace-management-and-resource-tracking"&gt;
&lt;h3&gt;Persistent memory namespace management and resource tracking&lt;/h3&gt;
&lt;p&gt;Due to the aforementioned fragmentation issue, persistent memory can not
be managed in the similar way as system memory. In other words,
dynamically creating and deleting persistent memory namespaces upon
VM creation and deletion will result in fragmentation and also a challenge
to track persistent memory resource.
The proposed approach is to use pre-created fix sized namespaces.
In other words, the cloud admin creates persistent memory of the desired
sizes before Nova is deployed on a certain host. And the cloud admin puts
the namespace information into nova config file (details below).
Nova compute agent discovers the namespaces by parsing the config file
to determine what namespaces it can allocate to a guest. The discovered
persistent memory namespaces will be reported to the placement service
as inventories of a custom resource class associated with the ROOT
resource provider.&lt;/p&gt;
&lt;p&gt;Custom Resource Classes are used to represent persistent memory namespace
resource. The naming convention of the custom resource classes being used is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;CUSTOM_PMEM_NAMESPACE_$LABEL
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$LABEL&lt;/span&gt;&lt;/code&gt; is variable part of the resource class name defined by the admin
to be associated with a certain number of persistent memory namespaces.
It normally is the size of namespaces in any desired units.
It can also be a string describing the capacities – such as ‘SMALL’,
‘MEDIUM’ or ‘LARGE’. Admin shall properly define the value of ‘$LABEL’
for each namespace.&lt;/p&gt;
&lt;p&gt;The association between &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$LABEL&lt;/span&gt;&lt;/code&gt; and persistent memory namespaces
is defined by a new configuration option ‘CONF.libvirt.pmem_namespaces’.
This config option is of string type in below format:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="s2"&gt;"$LABEL:$NSNAME[|$NSNAME][,$LABEL:$NSNAME[|$NSNAME]]"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$NSNAME&lt;/span&gt;&lt;/code&gt; is the name of the persistent memory namespace that falls
into the resource class named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PMEM_NAMESPACE_$LABEL&lt;/span&gt;&lt;/code&gt;.
A name can be given to a persitent memory namespace upon creation by
the “-n/–name” option to the &lt;a class="reference external" href="http://pmem.io/ndctl/"&gt;ndctl&lt;/a&gt; command.&lt;/p&gt;
&lt;p&gt;To give an example, on a certain host, there might be a below configuration:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="s2"&gt;"128G:ns0|ns1|ns2|ns3,262144MB:ns4|ns5,MEDIUM:ns6|ns7"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The interpretation of the above configuration is that this host has 4
persistent memory namespaces (ns0, ns1, ns2, ns3) of resource class
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PMEM_NAMESPACE_128G&lt;/span&gt;&lt;/code&gt;, 2 namespaces (ns4, ns5) of resource class
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PMEM_NAMESPACE_262144MB&lt;/span&gt;&lt;/code&gt;, and 2 namespaces (ns6, ns7) of resource
class &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PMEM_NAMESPACE_MEDIUM&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The ‘total’ value of the inventory is the &lt;em&gt;number&lt;/em&gt; of the
persistent memory namespaces belong to this resource class.&lt;/p&gt;
&lt;p&gt;The ‘max_unit’ is set to the same value as ‘total’ since it is possible
to attach all of the persistent memory namespaces in a certain resource
class to one instance.&lt;/p&gt;
&lt;p&gt;The values of ‘min_unit’ and ‘step_size’ are 1.&lt;/p&gt;
&lt;p&gt;The value of ‘allocation_ratio’ is 1.0.&lt;/p&gt;
&lt;p&gt;In case of the above example, the response to a &lt;cite&gt;GET&lt;/cite&gt; request to this
resource provider inventories is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="s2"&gt;"inventories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="s2"&gt;"CUSTOM_PMEM_NAMESPACE_128GB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"allocation_ratio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"max_unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"min_unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"reserved"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"step_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"CUSTOM_PMEM_NAMESPACE_262144MB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"allocation_ratio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"max_unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"min_unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"reserved"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"step_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"CUSTOM_PMEM_NAMESPACE_MEDIUM"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"allocation_ratio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"max_unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"min_unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"reserved"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"step_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Please note, this is just an example to show different ways to configure
persistent memory namespaces and how they are tracked. There are certainly
some flexibility in the naming of the resource class name. It is up to
the admin to configure the namespaces properly.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Resource class names are opaque. For example, a request
for CUSTOM_PMEM_NAMESPACE_128GB cannot be fulfilled by a
CUSTOM_PMEM_NAMESPACE_131072MB resource even though they are
(presumably) the same size.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Different units do not convert freely from one to another while embeded
in custom resource class names. Meaning a request for a 128GB persistent
memory namespace can be fulfilled by a CUSTOM_PMEM_NAMESPACE_128GB
resource, but can not be fulfilled by a CUSTOM_PMEM_NAMESPACE_131072MB
resource even though they are of the same quantity.&lt;/p&gt;
&lt;p&gt;Persistent memory is by nature NUMA sensitive. However for the initial
iteration, the resource inventories are put directly under ROOT resource
provider of the compute host. Persistent memory NUMA affinity will be
addressed by a separate follow-on spec.&lt;/p&gt;
&lt;p&gt;A change in the configuration will stop the nova compute agent from
(re)starting if that change removes any namespaces in use by guests
from the configuration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="virtual-persistent-memory-specification"&gt;
&lt;h3&gt;Virtual persistent memory specification&lt;/h3&gt;
&lt;p&gt;Virtual persistent memory information is added to guest hardware flavor
extra specs in the form of:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;hw:pmem=$LABEL[,$LABEL]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;$LABEL&lt;/span&gt;&lt;/code&gt; is the variable part of a resource class name as defined
in the &lt;a class="reference internal" href="#persistent-memory-namespace-management-and-resource-tracking"&gt;Persistent memory namespace management and resource tracking&lt;/a&gt;
section. Each appearence of a ‘$LABEL’ means a requirement to one
persistent memory namespace of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_PMEM_NAMESPACE_$LABEL&lt;/span&gt;&lt;/code&gt;
resource class. So there can be multiple appearences of the same
$LABEL in one specification. To give an example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pmem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It means a resource requirement of two 128GB persisent memory
namespaces.&lt;/p&gt;
&lt;p&gt;Libvirt domain specification requires each virtual persistent memory
to be associated with one guest NUMA node. If guest NUMA topology
is specified in the flavor, the guest virtual persistent memory
devices are put under guest NUMA node 0. If guest NUMA topology is not
specified in the flavor, a guest NUMA node 0 is constructed implicitly
and all guest virutal persistent memory devices are put under it.
Please note, under the second circumstance (implicitly constructing
a guest NUMA node 0), the construction of guest NUMA node 0 happens
at the Nova API, which means the NUMA topology logic in the scheduler
is applied. And from the perspective of any other parts of Nova, this
guest is a NUMA guest.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;One&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;numa_nodes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pmem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;

&lt;span class="n"&gt;One&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;numa_nodes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pmem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;

&lt;span class="n"&gt;Two&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;numa_nodes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pmem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;

    &lt;span class="n"&gt;Both&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;devices&lt;/span&gt;
    &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;put&lt;/span&gt; &lt;span class="n"&gt;under&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;

&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pmem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;

    &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;guest&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;constructed&lt;/span&gt; &lt;span class="n"&gt;implicitly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Both&lt;/span&gt; &lt;span class="n"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;persistent&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;devices&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;put&lt;/span&gt; &lt;span class="n"&gt;under&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Qemu does not support backing one virtual persistent memory device
by multiple physical persistent memory namespaces, no matter whether
they are contiguous or not. So any virtual persistent memory device
requested by guests is backed by one physical persistent memory
namespace of the exact same resource class.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The extra specs are translated to placement API requests accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="virtual-persistent-memory-disposal"&gt;
&lt;h3&gt;Virtual persistent memory disposal&lt;/h3&gt;
&lt;p&gt;Due to the persistent nature of host PMEM namespaces, the content
of virtual persistent memory in guests shall be zeroed out immediately
once the virtual persisent memory is no longer associated with any VM
instance (cases like VM deletion, cold/live migration, shelve, evacuate
and etc.). Otherwise there will be security concerns.
Since persistent memory devices are typically of large size, this may
introduce a performance penalty to guest deletion or any other actions
involving erasing PMEM namespaces.
The standard I/O APIs (read/write) cannot be used with DAX (direct access)
devices. The nova compute libvirt driver uses &lt;a class="reference external" href="http://pmem.io/pmdk/daxio/"&gt;daxio&lt;/a&gt; utility (wrapped
by privsep library functions) for this purpose.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vm-rebuild"&gt;
&lt;h3&gt;VM rebuild&lt;/h3&gt;
&lt;p&gt;The persisent memory namespaces are zeroed out during VM rebuild to
get to the initial state of the VM.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vm-resize"&gt;
&lt;h3&gt;VM resize&lt;/h3&gt;
&lt;p&gt;Resizing to new flavor with arbitrary virtual persistent memory devices
is allowed. The content of the original virtual persistent memory will not
be copied to the new virtual persistent memory (if there is).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="live-migration"&gt;
&lt;h3&gt;Live migration&lt;/h3&gt;
&lt;p&gt;Live migration with virtual persistent memory is supported by QEMU.
Qemu treats virtual persistent memory as volatile memory in case of
live migration. It just takes longer time due to the typical large
capacity of virtual persistent memory.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="virtual-persistent-memory-hotplug"&gt;
&lt;h3&gt;Virtual persistent memory hotplug&lt;/h3&gt;
&lt;p&gt;This spec does not address the hot plugging of virtual persistent memory.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vm-snapshot"&gt;
&lt;h3&gt;VM snapshot&lt;/h3&gt;
&lt;p&gt;The current VM snapshots do not include memory images. For the current
phase the virtual persistent images are not included in the VM snapshots.
In future, virtual persistent images could be stored in Glance as a separate
image format. And flavor extra specs can be used to specify whether
to save virtual persistent memory image during VM snapshot.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="vm-shelve-unshelve"&gt;
&lt;h3&gt;VM shelve/unshelve&lt;/h3&gt;
&lt;p&gt;Shelving a VM is to upload the VM snapshot to Glance service. Since the
virtual persistent memory image is not included in the VM snapshot,
VM shelve/unshelve does not automatically save/restore the virtual
persistent memory for the current iteration.
As snapshot, saving/restoring virtual persistent memory images could be
supported after the persistent memory images can be stored in Glance.
The persistent memory namespaces belong to a shelved VM are zeored out
after VM being shelve-offloaded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Persisent memory namespaces can be created/destroyed on the fly as VM
creation/deletion. This ways is more flexible than the fix sized
approach, however it will result in fragmentation as detailed in the
&lt;a class="reference internal" href="#background"&gt;Background&lt;/a&gt; section.&lt;/p&gt;
&lt;p&gt;Another model of fix sized appoach other than the proposed one could
be evenly partitioning the entire persistent memory space into namespaces
of the same size and setting the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;step_size&lt;/span&gt;&lt;/code&gt; of the persistent
memory resource provider to the size of each namespace. However this
model assumes a larger namespace can be assembled from multiple smaller
namespaces (a 256GB persistent memory requirement may land on 2x128GB
namespaces) which is not the case.&lt;/p&gt;
&lt;p&gt;Persistent memory demonstrates certain similarity with block devices
in its non-volatile nature and life cycle management. It is possible
to stick it into block device mapping (BDM) interface. However, NUMA
affinity support is in the future of persistent memory and BDM is not
the ideal interface to decribe NUMA.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new LibvirtVPMEMDevice object is introduced to track the virtual PMEM
information of an instance, it stands for a virtual persistent memory
device backed by a physical persistent memory namespace:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;LibvirtVPMEMDevice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResourceMetadata&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Version 1.0: Initial version&lt;/span&gt;
    &lt;span class="n"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;

    &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="s1"&gt;'label'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
       &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
       &lt;span class="s1"&gt;'size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
       &lt;span class="s1"&gt;'devpath'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
       &lt;span class="s1"&gt;'align'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntegerField&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The ‘resources’ deferred-load column in class InstanceExtra stores a serialized
ResourceList object for a given instance, each Resource object contain a
specific resource information, it has a object field ‘metadata’, which can be
subclass of ResourceMetadata object. Since LibvirtVPMEMDevice is introduced,
virtual persistent memory information can be stored in ‘resources’ field of
objects.Instance and persistent in database table InstanceExtra.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Flavor extra specs already accept arbitrary data.
No new micro version introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Host persistent memory namespaces needs to be erased (zeroed) to be reused.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;End users choose flavors with desired virtual persistent memory sizes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;PMEM namespaces tend to be large. Zeroing out a persistent memory
namespace requires a considerable amount of time. This may introduce
a negative performance impact when deleting a guest with large
virtual persistent memories.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;The deployer needs to create persistent memory namespaces of the desired
sizes before nova is deployed on a certain host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;xuhj&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;luyaozhong
rui-zang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Object: add DB model and Nova object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compute: virtual persistent memory life cycle management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Scheduler: translate virtual persistent memory request to&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;placement requests.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API: parse virtual persistent memory flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Kernel version &amp;gt;= 4.18&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;NVDIMM support is present in the Linux Kernel v4.0 or newer. It is
recommended to use Kernel version 4.2 or later since &lt;a class="reference external" href="https://docs.pmem.io/persistent-memory/getting-started-guide/creating-development-environments/linux-environments"&gt;NVDIMM support&lt;/a&gt;
is enabled by default. We met some bugs in older versions,
and we have done all verification works with OpenStack on 4.18 version,
so 4.18 version and newer will probably guarantee its functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;QEMU version &amp;gt;= 3.1.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libvirt version &amp;gt;= 5.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ndctl version &amp;gt;= 62&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;daxio version &amp;gt;= 1.6&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests.
Third party CI is required for testing on real hardware.
Persistent memory nested virtualization works for QEMU/KVM.
For the third party CI, tempest tests are executed in a VM with
virtual persisent memory backed by physical persistent memory.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The cloud administrator docs need to describe how to create
and configure persistent memory namespaces. Add a persitent
memory section into the Nova “advanced configuration” document.&lt;/p&gt;
&lt;p&gt;The end user needs to be make aware of this feature. Add the
flavor extra spec details into the Nova flavors document.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Sat, 05 Sep 2020 00:00:00 </pubDate></item><item><title>Online Schema Changes</title><link>https://specs.openstack.org/openstack/nova-specs/specs/kilo/approved/online-schema-changes.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/online-schema-changes"&gt;https://blueprints.launchpad.net/nova/+spec/online-schema-changes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make schema changes execute online (ie while services are running) when
safely and semantically possible. This will allow operators to reduce the
amount of downtime currently required during deploys.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All database migrations are currently required to be run offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database migrations have historically been a source of lengthy downtime
during deployments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schema changes are required to be repeated in two places: database
model defined in Nova and writing a migration script.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Any deployer that would like to reduce the amount of downtime during
deploys.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Developers that would like to spend less time writing migration
scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployers that would like to maintain a set of local schema changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="project-priority"&gt;
&lt;h3&gt;Project Priority&lt;/h3&gt;
&lt;p&gt;This fits under the ‘Live Upgrades’ kilo priorities.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;A new alternative workflow for applying schema changes will be added
that expands the schema, then contracts the schema (expand/contract
workflow).&lt;/p&gt;
&lt;p&gt;The new expand/contract workflow will not utilize any migration scripts,
instead it will dynamically compare the running schema against the
database model defined in Nova. DDL statements will be generated, and
optionally executed, to make the running schema match the model.&lt;/p&gt;
&lt;p&gt;The existing schema management workflow is the ‘db sync’ command to
nova-manage. This is managed by sqlalchemy-migrate and uses individual
migration scripts. This workflow will remain for now, but is expected
to be removed at some future time, leaving the expand/contract
workflow as the way to manage the database schema.&lt;/p&gt;
&lt;p&gt;Until the sqlalchemy-migrate workflow is removed, all schema changes
will still need sqlalchemy-migrate migration scripts to be written.&lt;/p&gt;
&lt;p&gt;Three new nova-manage commands will be added:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;expand. This would apply changes that are compatible with old running
code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;migrate. This would apply changes that are necessary to be run offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;contract. This would apply changes that are compatible with new
running code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Those schema changes that can be safely and semantically applied while
running online will be applied during the expand and contract phases.
Also, only those schema changes that will not acquire long running
locks in the database will be considered for the online phases (expand,
contract). All other schema changes will be applied during the migrate
phase.&lt;/p&gt;
&lt;p&gt;The three new commands would be built by dynamically executing alembic’s
autogenerate and DDL generating features. A list of differences would
be generated by alembic and then DDL statements would be generated using
a separate feature of alembic.&lt;/p&gt;
&lt;p&gt;The set of DDL statements that can be run in each phase would be dictated
by the database software used (eg MySQL, PostgreSQL, etc), the version of
the database software (eg MySQL 5.5, 5.6, etc) and the storage engine used
(eg InnoDB, TokuDB, etc).&lt;/p&gt;
&lt;p&gt;As an example, index additions can be executed online in MySQL 5.5, but
not 5.1. An index addition would be run during the expand phase for
MySQL 5.5 or higher, but during the migrate phase for MySQL 5.1.&lt;/p&gt;
&lt;p&gt;It is intended that the initial set that will run online will be
conservative at first and a subset of what is possible to run safely.
This can be safely expanded at any time in the future.&lt;/p&gt;
&lt;p&gt;Schema changes that will be potentially performed during expand:
- Table creates
- Column additions
- Non-Unique Index additions&lt;/p&gt;
&lt;p&gt;Schema changes that will be potentially performed during migrate:
- Unique Index additions/drops
- Foreign Key additions/drops&lt;/p&gt;
&lt;p&gt;Schema changes that will be potentially performed during contract:
- Table drops
- Column drops
- Non-Unique Index drops&lt;/p&gt;
&lt;p&gt;Some schema changes that aren’t currently used or are difficult to
automate will not be allowed initially. For instance, column type
changes will not be allowed initially. This is because not all column
type changes can be automated because of complexity and database
restrictions. A subset of column type changes may be implemented in
the future if they can be automated on all databases.&lt;/p&gt;
&lt;p&gt;The migrate and contract phases would verify that the previous phases
(expand in the case of migrate, expand and migrate in the case of
contract) no longer need to be executed before continuing.&lt;/p&gt;
&lt;p&gt;This would be performed by generating the list of needed changes for
the previous phases and verifying the list is empty. This indicates the
previous phases were either run or unnecessary.&lt;/p&gt;
&lt;p&gt;A new ‘–dryrun’ argument would print, instead of execute, each
generated DDL statement. This could be used by database administrators
to see what would be executed for a particular phase. These can be
optionally executed manually if desired. The schema synchronizer will
not generate that DDL statement since the running schema does not
have that difference anymore.&lt;/p&gt;
&lt;p&gt;When ‘db contract’ is finally run and the running schema has been
verified to match the models, the version in the migrate_version
table would be updated to the latest shipped sqlalchemy-migrate
migration version. This would maintain compatibility with the
existing sqlalchemy-migrate workflow.&lt;/p&gt;
&lt;p&gt;The fundamental difference between the two workflows is the
expand/contract workflow is declarative (by using the model) and the
sqlalchemy-migrate workflow is imperative (by using migration scripts).&lt;/p&gt;
&lt;p&gt;By being declarative, it limits changes to one place (database model)
and allows for more intelligent decisions (by factoring in the database
software, engine, version, etc)&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Splitting the existing single stream of migrations into three separate
streams of migrations. This would allow some schema changes to be
executed online.&lt;/p&gt;
&lt;p&gt;This limits the schema changes that can be safely executed online to
that of the lowest common denominator of databases supported by Nova.&lt;/p&gt;
&lt;p&gt;This would also require changes to sqlalchemy-migrate to be able to
manage separate streams of migrations.&lt;/p&gt;
&lt;p&gt;Another option would be remove the use of sqlalchemy-migrate for schema
changes altogether. The ‘db sync’ command to nova-manage would be
implemented by effectively calling ‘db expand’, ‘db migrate’ and
‘db contract’.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Running online DDL changes can affect the performance of a running system.
This is optional and is only done when the deployer explicitly requests
it.&lt;/p&gt;
&lt;p&gt;This can mitigated by the deployer by scheduling the expand and contract
phases to be run during periods of low activity. The expand phase can
be run an arbitrary amount of time before the migrate phase. Likewise,
the contract phase does not need to be run immediately after the
migrate phase is run.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Using the new expand/contract workflow is optional. If the deployer
does not want to perform database schema changes online, then they
can continue using the ‘db sync’ command with nova-manage.&lt;/p&gt;
&lt;p&gt;Those deployers that want to take advantage of the online schema changes
will need to run the ‘db expand’, ‘db migrate’ and ‘db contract’ commands
at the appropriate steps in their deployment process.&lt;/p&gt;
&lt;p&gt;Switching from the sqlalchemy-migrate workflow to the expand/contract
workflow can happen at any time. The reverse can only happen after
a final ‘db contract’ is run (to ensure all schema changes are applied
and the migrate_version table is updated).&lt;/p&gt;
&lt;p&gt;If the expand/contract workflow is used, then ‘db contract’ is required
to be execute once for each formal release of Nova. This is to ensure
that SQL namespaces (table, column, etc) can be reused in the future.&lt;/p&gt;
&lt;p&gt;Deployers that have made local schema changes (extra indexes, columns,
tables, etc) will need to update the model to ensure those additions
aren’t dropped during the contract phase.&lt;/p&gt;
&lt;p&gt;If using the expand/contract workflow, then deployers can run ‘db expand’
before stopping or restarting any services. ‘db migrate’ might acquire
locks in the database and may affect running services. ‘db contract’ can
be run after all Nova services are running the new code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Eventually no more sqlalchemy-migrate migrations would need to be written
leading to less work for developers.&lt;/p&gt;
&lt;p&gt;No more migration compaction. The initial creation of tables for a
database is handled completely by the schema synchronizer.&lt;/p&gt;
&lt;p&gt;Some schema changes will no longer be allowed. This is generally
restricted to schema changes that cannot be reasonably automated but
those schema changes are generally the ones with the most downtime
anyway.&lt;/p&gt;
&lt;p&gt;Namespaces (table, column, index, etc) are not reusable in a formal
release cycle. The contract phase is only required to be executed once
per formal release, pinning old names until the next formal release.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johannes.erdfelt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement schema synchronizer using alembic.autogenerate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement new ‘expand’, ‘migrate’ and ‘contract’ commands to
‘nova-manage db’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure grenade and turbo-hipster tests are update&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This builds on top of the validate-migrations-and-model spec. The
existing use of alembic.autogenerate will now also be used to generate
the list of needed changes to make the schema match the model.&lt;/p&gt;
&lt;p&gt;This also depends on dropping the use of sqlalchemy-migrate for data
migrations.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;No tempest tests will be added since tempest does not do any upgrade
testing.&lt;/p&gt;
&lt;p&gt;A Nova unit test will be added to test starting from an empty database.&lt;/p&gt;
&lt;p&gt;Grenade currently tests upgrades from older versions of Nova. A new
test to use the new ‘db expand’, ‘db migrate’ and ‘db contract’ commands
are necessary. This will be compared with the result of ‘db sync’ to
ensure that upgrades from past commits end up semantically identical.&lt;/p&gt;
&lt;p&gt;turbo-hipster tests upgrades using production database snapshots. It
currently uses the ‘db sync’ command to nova-manage. The new
expand/contract workflow will be tested as well to ensure that both
workflows function correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Documentation will need to be updated to include the new ‘expand’,
‘migrate’ and ‘contract’ commands to ‘nova-manage db’.&lt;/p&gt;
&lt;p&gt;Release Notes will need to be updated to warn that the model will need
to be updated with local schema changes.&lt;/p&gt;
&lt;p&gt;Instance Types would need to be manually created as the 216 migration
would not necessarily run anymore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/kilo-nova-zero-downtime-upgrades"&gt;https://etherpad.openstack.org/p/kilo-nova-zero-downtime-upgrades&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 02 Sep 2020 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/wallaby/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/nova/tree/nova/api/openstack/compute/schemas"&gt;http://git.openstack.org/cgit/openstack/nova/tree/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Wallaby&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 17 Aug 2020 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/template.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/example"&gt;https://blueprints.launchpad.net/nova/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.&lt;/p&gt;
&lt;p&gt;Some notes about the nova-spec and blueprint process:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not all blueprints need a spec. For more information see
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs"&gt;https://docs.openstack.org/nova/latest/contributor/blueprints.html#specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The aim of this document is first to define the problem we need to solve,
and second agree the overall approach to solve that problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is not intended to be extensive documentation for a new feature.
For example, there is no need to specify the exact configuration changes,
nor the exact details of any DB model changes. But you should still define
that such changes are required, and be clear on how that will affect
upgrades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should aim to get your spec approved before writing your code.
While you are free to write prototypes and code before getting your spec
approved, its possible that the outcome of the spec review process leads
you towards a fundamentally different solution than you first envisaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, API changes are held to a much higher level of scrutiny.
As soon as an API change merges, we must assume it could be in production
somewhere, and as such, we then need to support that API change forever.
To avoid getting that wrong, we do want lots of details about API changes
upfront.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some notes about using this template:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your spec should be in ReSTructured text, like this template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please wrap text at 79 columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The filename in the git repository should match the launchpad URL, for
example a URL of: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/nova/+spec/awesome-thing&lt;/a&gt;
should be named awesome-thing.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please do not delete any of the sections in this template.  If you have
nothing to say for a whole section, just write: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For help with syntax, see &lt;a class="reference external" href="http://sphinx-doc.org/rest.html"&gt;http://sphinx-doc.org/rest.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To test out your formatting, build the docs using tox and see the generated
HTML file in doc/build/html/specs/&amp;lt;path_of_your_file&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you would like to provide a diagram with your spec, ascii diagrams are
required.  &lt;a class="reference external" href="http://asciiflow.com/"&gt;http://asciiflow.com/&lt;/a&gt; is a very nice tool to assist with making
ascii diagrams.  The reason for this is that the tool used to review specs is
based purely on plain text.  Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit.  It
will also allow inline feedback on the diagram itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your specification proposes any changes to the Nova REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/nova-specs+message:apiimpact,n,z&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem. What problem is this blueprint
addressing?&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;What use cases does this address? What impact on actors does this change have?
Ensure you are clear about the actors in each use case: Developer, End User,
Deployer etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;p&gt;At this point, if you would like to just get feedback on if the problem and
proposed change fit in nova, you can stop here and post this for review to get
preliminary feedback. If so please say:
Posting to get preliminary feedback on the scope of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Changes which require modifications to the data model often have a wider impact
on the system.  The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.&lt;/p&gt;
&lt;p&gt;Questions which need to be addressed by this section include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What new data objects and/or database schema changes is this going to
require?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Each API method which is either added or changed should have the following&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specification for the method&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description of what the method does suitable for use in
user documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method type (POST/PUT/GET/DELETE)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;URL should not include underscores, and use hyphens instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the request body data if allowed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response body data if any&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Field names should use snake_case style, not CamelCase or MixedCase
style.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example use case including typical API samples for both data supplied
by the caller and the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example JSON schema definitions can be found in the Nova tree
&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/nova/tree/nova/api/openstack/compute/schemas"&gt;http://git.openstack.org/cgit/openstack/nova/tree/nova/api/openstack/compute/schemas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the schema should be defined as restrictively as
possible. Parameters which are required should be marked as such and
only under exceptional circumstances should additional parameters
which are not defined in the schema be permitted (eg
additionaProperties should be False).&lt;/p&gt;
&lt;p&gt;Reuse of existing predefined parameter types such as regexps for
passwords and user defined names is highly encouraged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Describe any potential security impact on the system.  Some of the items to
consider include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change touch sensitive data such as tokens, keys, or user data?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change alter the API in a way that may impact security, such as
a new way to access sensitive information or a new way to login?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve cryptography or hashing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change require the use of sudo or any elevated privileges?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this change involve using or parsing user-provided data? This could
be directly at the API level or indirectly such as changes to a cache layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can this change enable a resource exhaustion attack, such as allowing a
single API interaction to consume significant server resources? Some examples
of this include launching subprocesses for each connection, or entity
expansion attacks in XML.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more detailed guidance, please see the OpenStack Security Guidelines as
a reference (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines&lt;/a&gt;).  These
guidelines are a work in progress and are designed to help you identify
security best practices.  For further information, feel free to reach out
to the OpenStack Security Group at &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;openstack-security&lt;span&gt;@&lt;/span&gt;lists&lt;span&gt;.&lt;/span&gt;openstack&lt;span&gt;.&lt;/span&gt;org&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;p&gt;Consider proposing changes to the versioned notifications:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When the feature adds or removes fields to the API responses. For example
when the feature adds a new field to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; API response
consider adding similar information to the payload of the instance action
notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new action to the existing API entities. For example
adding a new action to the server might mean you want to emit a corresponding
new instance action notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the feature adds a new resource (noun) to the REST API consider adding
new notifications about the creation and deletion of such resource&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Aside from the API, are there other ways a user will interact with this
feature?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does this change have an impact on python-novaclient and openstack client?
What does the user interface there look like?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Describe any potential performance impact on the system, for example
how often will new code be called, and is there a major change to the calling
pattern of existing code.&lt;/p&gt;
&lt;p&gt;Examples of things to consider here include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A periodic task might look like a small addition but if it calls conductor or
another service the load is multiplied by the number of nodes in the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler filters get called once per host for every instance being created,
so any latency they introduce is linear with the size of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small change in a utility function or a commonly used decorator can have a
large impacts on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in a database queries (whether direct or via conductor)
can have a profound impact on performance when called in critical sections of
the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will the change include any locking, and if so what considerations are there
on holding the lock?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this change is a new binary, how would it be deployed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features.  For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed?  Do we move them?  Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Discuss things that will affect other developers working on OpenStack,
such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Describe any potential upgrade impact on the system, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this change adds a new feature to the compute host that the controller
services rely on, the controller services may need to check the minimum
compute service version in the deployment before using the new feature. For
example, in Ocata, the FilterScheduler did not use the Placement API until
all compute services were upgraded to at least Ocata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While we strive to have feature parity between all virt drivers, it is not
uncommon for one virt driver to implement a new feature exposed out of the
API before the others. For example, extending the size of an attached
volume. Since Nova does not yet have any type of sophisticated &lt;em&gt;capabilities&lt;/em&gt;
API so a user can know what actions can be performed on a given instance,
consider adding a new policy rule to at least let operators that cannot
support a virt-specific feature disable it in their cloud which is at least
presented to the user in an understandable way by getting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;403&lt;/span&gt; &lt;span class="pre"&gt;Forbidden&lt;/span&gt;&lt;/code&gt;
error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova supports N-1 version &lt;em&gt;nova-compute&lt;/em&gt; services for rolling upgrades. Does
the proposed change need to consider older code running that may impact how
the new change functions, for example, by changing or overwriting global
state in the database? This is generally most problematic when making changes
that involve multiple compute hosts, like move operations such as migrate,
resize, unshelve and evacuate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the writing of the code? Or is this a blueprint where you’re
throwing it out there to see who picks it up?&lt;/p&gt;
&lt;p&gt;If more than one person is working on the implementation, please designate the
primary author and contact.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;Ideally feature work is sponsored by a member of the &lt;a class="reference external" href="https://review.opendev.org/#/admin/groups/25,members"&gt;nova core team&lt;/a&gt; or
other experienced and active nova developer. The purpose of a liaison is
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mentor developers through the arcana of nova’s development processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advocate for (aka “care about”) the feature to the rest of the nova team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be the initial go-to for reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;name and/or nick&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature liaison is optional. However we suggest to find a liaison for
your feature as it will help getting your feature merged. The
&lt;a class="reference internal" href="../../readme.html#feature-liaisons"&gt;&lt;span class="std std-ref"&gt;Feature Liaison FAQ&lt;/span&gt;&lt;/a&gt; has details about how to find a liaison for your
work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you do not already have agreement from a nova developer to act as
your liaison, you may write “Liaison Needed” here and/or in your
commit message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are a core or experienced nova dev, you need not have a
separate liaison; if you wish, you may just assign yourself, or put
“None”/”N/A”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in nova, or in other
projects, that this one either depends on or is related to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this requires functionality of another project that is not currently used
by Nova (such as the glance v2 API when we previously only required v1),
document that fact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Please discuss the important scenarios needed to test here, as well as
specific edge cases we should be ensuring work correctly. For each
scenario please specify if this requires specialized hardware, a full
openstack environment, or can be simulated inside the Nova tree.&lt;/p&gt;
&lt;p&gt;Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.&lt;/p&gt;
&lt;p&gt;Is this untestable in gate given current limitations (specific hardware /
software configurations available)? If so, are there mitigation plans (3rd
party testing, gate enhancements, etc).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Which audiences are affected most by this change, and which documentation
titles on docs.openstack.org should be updated because of this change? Don’t
repeat details discussed above, but reference them here in the context of
documentation for multiple audiences. For example, the Operations Guide targets
cloud operators, and the End User Guide would need to be updated if the change
offers a new feature available through the CLI or dashboard. If a config option
changes or is deprecated, note here that the documentation needs to be updated
to reflect this specification’s change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Links to mailing list or IRC discussions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to notes from a summit session&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links to relevant research, if appropriate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related specifications as appropriate (e.g.  if it’s an EC2 thing, link the
EC2 docs)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anything else you feel it is worthwhile to refer to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;Optional section intended to be used each time the spec is updated to describe
new design, API or any database schema updated. Useful to let reader understand
what’s happened along the time.&lt;/p&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 21 Jul 2020 00:00:00 </pubDate></item><item><title>Scheduling support for Routed Networks</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/routed-networks-scheduling.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/routed-networks-scheduling"&gt;https://blueprints.launchpad.net/nova/+spec/routed-networks-scheduling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Neutron provides network segments support thanks to Routed Networks where you
can create a port allocated to a specific segment. Unfortunately, Nova doesn’t
verify the segment at every instance operation, including those where you move
an instance, which leads to inconsistencies.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Although it’s possible to create a Neutron port with a routed networks setup
and boot an instance with this port, the network locality of the compute node
associated with the instance won’t be verified by the scheduler and could
lead to a wrong scheduling decision. This is problematic when a move operation
sends an instance to a compute node that isn’t in the network segment that is
related to the IP address that was allocated at boot time.&lt;/p&gt;
&lt;p&gt;As a result of this gap, the only way to use routed networks in Nova currently
is by creating a port having the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation&lt;/span&gt;&lt;/code&gt; value be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deferred&lt;/span&gt;&lt;/code&gt; and
making sure that all compute services are assigned to at least one network
segment.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I’d like to make sure that instances IP addresses can be
correctly separated between the network segments I provided.&lt;/p&gt;
&lt;p&gt;As an operator, I don’t want to see instances going to compute services that
aren’t in network segments if the user asks for either a port or a routed
network.&lt;/p&gt;
&lt;p&gt;As a user, I’d like Nova to place my instance on the correct host  according to
the port or network I’ve requested for my instance, without having to
specifically create a port with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ip_allocation=deferred&lt;/span&gt;&lt;/code&gt; value.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Once you &lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-routed-networks.html"&gt;configure routed networks in Neutron&lt;/a&gt;, network segments are
represented as Placement Resource Providers. Neutron will then ask Nova to
create a Nova host aggregate for each segment and will add compute services
that are mapped with respective segments into the related aggregates.
Eventually, Nova will mirror those aggregates into Placement aggregates.&lt;/p&gt;
&lt;p&gt;What we then need for Nova is to have a way for asking the Placement API to
only get resource providers (i.e. compute nodes) that are in the aggregate
related to the segments that are in the network passed by the user (or related
to the port that is asked).&lt;/p&gt;
&lt;p&gt;As Nova needs to find which segments are related and then which aggregates,
we could just provide a new pre-filter that would look at it if some
configuration option (say &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;query_placement_for_routed_network_aggregates&lt;/span&gt;&lt;/code&gt;)
would be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A pseudo-code for it would be :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;support_routed_networks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_spec&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_placement_for_routed_network_aggregates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
  &lt;span class="n"&gt;segment_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;get_all_segments_ids_from_network_or_port&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;segment&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;segment_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="n"&gt;agg_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;get_provider_aggregates_from_segment_id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;append_agg_info_to_required_aggregates&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As said below in the &lt;a class="reference internal" href="#alternatives"&gt;Alternatives&lt;/a&gt; section, we could have Neutron passing
directly the aggregates, so this pre-filter could be deprecated once we
do it.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of having a new pre-filter, we could provide a specific scheduler
filter. This said, given we limit the number of allocation candidates returned
by Placement, we could miss some good resource providers so the filter couldn’t
work.&lt;/p&gt;
&lt;p&gt;Another alternative would be to have Neutron passing directly the needed
aggregate to Nova instead of Nova asking Neutron for it, but that would mean
that we should modify Neutron to return the Placement needed query in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;port.resource_request&lt;/span&gt;&lt;/code&gt; attribute.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;We may need to augment the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; object to be able to provide in its
nested &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestLevelParams&lt;/span&gt;&lt;/code&gt; object attribute the specific aggregate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There could be a performance impact if we would verify the segments for every
instance in every cloud, but given we ask the operator to modify an option
if they want to use routed networks, we don’t really think this would be an
issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new configuration option would be:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoolOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"query_placement_for_routed_network_aggregates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bauzas&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;bauzas&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a new pre-filter that would find the related aggregate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the aggregate to the RequestSpec asking to verify it by Placement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That’s it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional tests of course, but Tempest tests would be nice as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Maybe modifying &lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-routed-networks.html"&gt;https://docs.openstack.org/neutron/latest/admin/config-routed-networks.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Jun 2020 00:00:00 </pubDate></item><item><title>Unified Limits Integration in Nova</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/unified-limits-nova.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/unified-limits-nova"&gt;https://blueprints.launchpad.net/nova/+spec/unified-limits-nova&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec is about adopting Keystone’s unified-limits.
Includes using oslo.limit to enforce the Nova related limits set in Keystone.&lt;/p&gt;
&lt;p&gt;This spec proposes having unified limits in parallel with the existing
quota system for at least one cycle, to allow for operators to transition
from setting quotas via Nova to setting limits relating to the Nova API
endpoint via Keystone.&lt;/p&gt;
&lt;p&gt;All per user quota support is dropped, in favor of hierarchical
enforcement that will be supported by unified limits.&lt;/p&gt;
&lt;p&gt;Only server count limits and limits on Resource Class resources requested in
the flavor will be supported with unified limits. All other existing quotas
will no longer support per project or per user limits.&lt;/p&gt;
&lt;p&gt;Given this placement focused approach, we will depend on the work done here:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;While much work has been done to simplify how quotas are implemented in
Nova, there are still some major usability issues for operators with
the current system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We don’t have consistent support for limit/quota hierarchy across OpenStack&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requiring operators to set limits individually in each service
(i.e. Cinder, Nova, Neutron, etc)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova’s existing quotas don’t work well with Ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No support for custom Resource Class quotas (includes “per flavor” quotas)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confusion when API defined quota limits override any changes made to the
configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some Nova quotas are unrelated to resource consumption, causing confusion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transitioning to use Keystone’s unified limits, via oslo.limit, will help fix
these issues.&lt;/p&gt;
&lt;p&gt;For more details on unified limits in keystone see:
&lt;a class="reference external" href="https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html"&gt;https://docs.openstack.org/keystone/stein/admin/identity-unified-limits.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The key use cases driving this work are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API User tries to understand why they got an Over Quota error&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator migrates to unified limits from existing limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator sets a default limit for a given endpoint via Keystone. Note there
can be different limits for each Region, even with a shared Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator sets specific limits for a given project via Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator defines limits of a set of projects via non-flat enforcement
i.e. the feature formally known as hierarchical quotas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will focus on adding unified limits relating to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;total number of servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amounts of each Resource Class requested in the flavor&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note, this includes things like DISK_GB which is not supported today,
along with things like custom resource class resources that are requested
in extra specs (e.g. Ironic flavors).&lt;/p&gt;
&lt;p&gt;We will now look at all quotas exposed via the API and what they map to
when using unifed limits:
&lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota"&gt;https://docs.openstack.org/api-ref/compute/?expanded=show-a-quota-detail#show-a-quota&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The follow existing quota types move to unified limits, allowing for
per endpoint defaults and per project overrides (and hierarchical limits)
via the unified limits system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cores&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource:VCPU&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_count&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ram&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource:MEMORY_MB&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following existing quota becomes defined only by a configuration
option, and we no longer support and per project or user overrides
via the API, we just report the existing limit as defined in the
configuration:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_pairs&lt;/span&gt;&lt;/code&gt; (counted per user)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt; (counted per project)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt; (counted per server group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;metadata_items&lt;/span&gt;&lt;/code&gt; (counted per server)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above are purely protecting database bloat (i.e to stop a denial
of service attack that fills up the database). They are similar to the
hardcoded limit of the number of tags you can attach to a server.&lt;/p&gt;
&lt;p&gt;While deprecated in the API, we will also treat these quotas in the
same way as the quotas above, i.e. they will now be set via
confirguration with no per project overrides possible:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are several parts to this spec:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enforce Unified Limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No per-user limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No uncountable limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate Nova’s Quota APIs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator tooling to assist with the migration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="enforcing-unified-limits"&gt;
&lt;h3&gt;Enforcing Unified Limits&lt;/h3&gt;
&lt;p&gt;We will support the following limits:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_count&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource:&amp;lt;RESOURCE_CLASS&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the resource class usage will be counted using placement, but
server count will make use of instance mappings. This only works if the
queued for delete data migration has been completed. Due to no user
based quotas, we don’t need the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; migration. If the operators
tries to use unified limits before completing the migration, the code
will block all new usage until the migration is completed. It is
expected a blocking migration will be added before we turn on unified
limits by default. For more details on the this data migration see
this point in the existing quota code:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053"&gt;https://github.com/openstack/nova/blob/0d3aeb0287a0619695c9b9e17c2dec49099876a5/nova/quota.py#L1053&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To allow the new system to co-exist with the older quota system, we add
the following configuration to allow operators to opt-into the new system
when the operator has migrated to unified limits, and the default will be
to use the older quota system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For further details on the transition, please see the update section of this
specification. Note the new unified limits code will have a hard dependency
on counting usage via placement; as such it will ignore the value of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.quota.count_usage_from_placement&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the existing quotas, &lt;cite&gt;instances&lt;/cite&gt; becomes &lt;cite&gt;server_count&lt;/cite&gt;,
&lt;cite&gt;cores&lt;/cite&gt; becomes &lt;cite&gt;resource:VCPU&lt;/cite&gt; and &lt;cite&gt;ram&lt;/cite&gt; becomes &lt;cite&gt;resource:MEMORY_MB&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;This work will re-use a lot of the new logic to query placement for resource
usage, and use the instance mapping table to count servers added in this spec:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To find out what resources a server will claim, we reuse this
code to extract the resources from any given flavor:
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387"&gt;https://github.com/openstack/nova/blob/2e85453879533af0b4d0e1178797d26f026a9423/nova/scheduler/utils.py#L387&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For server build, we use the above function to get the Resource Class
resource amounts for the requested flavor. This will then be checked using
olso.limit, which ensures the additional usage will not push the associated
project over any of its limits. The oslo.limit library is responsible for
counting all the current resource usage using a callback we provide that makes
use of placement to count the current resource usage.&lt;/p&gt;
&lt;p&gt;Once resources are claimed in placement, we optionally recheck the limits
to see if we were racing with other server builds to consume the last bits
of available quota. The only change is using oslo.limit to do the recheck.
That is, we will still respect the config: &lt;cite&gt;quota.recheck_quota&lt;/cite&gt;
Note: we do the first check of limits in nova-api, and the recheck in
nova-conductor after resource allocation in placement succeeds.&lt;/p&gt;
&lt;p&gt;It is a similar story with resize. Except in this case, we check that we can
claim resources for both the new flavor and old flavor at the same time.
Note that this is quite different to the current quota system, even when
counting usage via placement.&lt;/p&gt;
&lt;p&gt;For further details on the semantic changes relating to counting with
placement see:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note baremetal instances no longer claim any VCPU or MEMORY_MB resources.
With this method, baremetal instances can be limited using custom
resource class resources they request in the flavor.&lt;/p&gt;
&lt;p&gt;Should we choose to allow additional custom inventory entries
from hypervisor based compute nodes, such as &lt;cite&gt;{‘CUSTOM_GPU_V100’:1}&lt;/cite&gt;
we will be also be able to apply quotas on these resources.&lt;/p&gt;
&lt;p&gt;The oslo.limits library will likely add additional configuration options.
In particular, operators will need to specify the Nova API’s endpoint uuid
to oslo.limit, so it knows what unified limits apply to each particular
Nova API service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="no-per-user-limits"&gt;
&lt;h3&gt;No per user limits&lt;/h3&gt;
&lt;p&gt;Nova currently supports “per user” limits. They will no longer be supported
when:  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are no plans for migration tools, however it is expected that users
that need a similar model can test out using the unified limits support for
hierarchical limits, and report back on what could help others migrate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="no-uncountable-limits"&gt;
&lt;h3&gt;No uncountable limits&lt;/h3&gt;
&lt;p&gt;As stated above, the focus for unified limits is the instance count and
resource class allocations in placement. No other limits will be moved to
unified limits, as agreed with operators in the Train Forum session.&lt;/p&gt;
&lt;p&gt;There are limits that are specific to nova-network. These are all ready
deprecated. There are no plans to support these with unified limits turned on:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixed_ips&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;floating_ip&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security_group_rules&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;networks&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The remaining limits are all mainly used to protect the database from rogue
users using up all available space in the database and/or missuse the API as
some sort of storage system. As such, it is not expected that operators need
per project overrides for any of these limits. As such, we propose to drop
support for changing the limits via the API, and instead only allow changing
of the limits via a single configuration option that applies to all
projects in the system.&lt;/p&gt;
&lt;p&gt;The following limits will be changed to only be set via a single configuration
option that applies equally to all projects:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;metadata&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_files&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;injected_file_path_bytes&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_pairs&lt;/span&gt;&lt;/code&gt; (counted per user)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_groups&lt;/span&gt;&lt;/code&gt; (counted per project)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server_group_members&lt;/span&gt;&lt;/code&gt; (counted per server group)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the server_group_members are currently counted per user, but this
is frankly very confusing, so above we propose the simpler limit servers
in the server group. This seems consistent with removing per user limits for
all other project owned resources.&lt;/p&gt;
&lt;p&gt;Using a global configuration option only means:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;no per project overrides&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;no per user overrides&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;no changing of limits via the API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are limits on the amount of data that can be stored in various
Nova databases. There is no way to display a project’s usage of these limits,
which further demonstrates how these are different to the resource limits
unified limits has been designed for.&lt;/p&gt;
&lt;p&gt;Currently we honor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; for all of these quotas. This adds
significant code complexity, however most users never hit these limits and
they are all very soft limits. As such, when we transition to a single global
configuration value for all of these, we also will stop doing any rechecks.&lt;/p&gt;
&lt;p&gt;In summary the impact on the configuration options is:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; will have an updated description, noting what
functionality is lost when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.floating_ips&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.fixed_ips&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.security_groups&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;security_group_rules&lt;/span&gt;&lt;/code&gt;: remain deprecated, and will be ignored when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.metadata_items&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_files&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_file_content_bytes&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.injected_file_path_length&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.server_groups&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.server_groups_members&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.key_pairs&lt;/span&gt;&lt;/code&gt;:  these will all be
kept, but the description will be updated to note if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; all updates via the API are ignored.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="deprecate-nova-s-quota-apis"&gt;
&lt;h3&gt;Deprecate Nova’s Quota APIs&lt;/h3&gt;
&lt;p&gt;To query and set limits, Keystones APIs should be used. To query a user’s
usage, the Placement API should be used, assuming placement is happy
changing the default policy to allow users to query their usage.&lt;/p&gt;
&lt;p&gt;The one exception is server count can’t currently be checked via
Placement. When placement implements consumer records,
or similar, then all usage could be queried via Placement. To avoid
using a proxy API, users can do a server list API and count the number
of servers returned.&lt;/p&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; a best effort will be made to
keep the older micro-versions working by proxing API calls to Keystone and
Placement as needed. No quota related DB tables will be accessed when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This includes the follow API resources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;/limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/os-quota-sets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/os-quota-class-sets&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing tooling to set quotas should continue to operate, as long as it only
changes quotas relating to instances, cores and ram. Requests to change any
other quotas will be silently ignored. As one example, this should allow
Horizon to function as normal during the transition.&lt;/p&gt;
&lt;p&gt;When you list limits for quotas that are not supported in the new system, they
will instead show the configuration based limit that replaces the DB and API
based limits, e.g. for keypairs you always see the config based value, no
update via the API will ever be reflected back when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are some trade-offs with this approach:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Proxy APIs suck, but horizon must keep working as such all current operator
tooling around these existing APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We don’t need a micro version to enable/disable this proxy
of the quota APIs, as it doesn’t really change the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a future release when unifed limits becomes the default,
we should deprecate the APIs
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-quota-sets&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/os-quota-class-sets&lt;/span&gt;&lt;/code&gt; and tell users to talk to
the Keystone API instead. API based discovery of when Nova is enforcing
the limits set in Keystone is left for a future spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is expected the above API deprecation will follow the pattern used
by nova-network proxy APIs, i.e. the APIs return 404 in new microversions
but continue to work in older microversions. Its possible in the more
distant future the APIs could be removed by returning 410 error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rejecting updates to quotas that we were previously able to set would be a
breaking change in behaviour, and require a microversion. Adding a new API
microversion that returns BadRequest for unsupported quotas would be a nice
addition if we were not planning on deprecating the API in favor of calling
Keystone instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideally we would also deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; in favor of a cross project
agreed direction that is aware of both flat and hierarchical limit
enforcement. Howerver we do not yet have consenus on what direction
we take. For this spec, we leave &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; in its current form, even
though it does not report on all the types of resource usage we now
support have limits on, and even though it lists limits that can
now only be changed via the configuration file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When hierarchical limits are added, the per project usage information
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/limits&lt;/span&gt;&lt;/code&gt; does not mention anything about parent limits.
As such quota APIs may claim resources are available, but you will be
unable to build any new resources.
It is not clear what action the user can make to be able to build those new
resources. Operators can avoid this confusion by not over allocating quota.
We could extext the API to include a boolean to say if the limit has been
exceeded in the parent project, and as such the user is unable to consume
more resources even though their own usage is not over their own limits.
We could consider extending the API to include the usage of the full tree&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="migration-to-unified-limits"&gt;
&lt;h3&gt;Migration to Unified Limits&lt;/h3&gt;
&lt;p&gt;The migration of all users to unified limits is happening in three phases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;enable unified limits as an option, with migration path from existing quotas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;make unified limits the default, deprecate existing quota system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove existing quota system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To help with the transition we need operator tooling to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Set registered limits in Keystone for each Nova endpoint in Keystone,
based on current limits in DB and/or configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy per-project quotas set in Nova into Keystone unified-limits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator confirms unified limits works for them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drop all quota info from the DB to signal operator has completed transition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade status check to check there is no data left in quota DB tables&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note the setting of project limits and registered limits in keystone will
happen via files that are generated and passed to keystone-manage. This
allows fast-forward upgrades where no API are available during the migration
of limits from Nova to Keystone.&lt;/p&gt;
&lt;p&gt;There will be a new tool to setup the registered limits in keystone. It will
read from the Nova DB and configuration and generate a file. That file can be
by used with keystone-manage to register the current endpoint defaults in
keystone.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;generate_registered_limits&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following tool will generate the unified limits overrides (if any)
that needs to be added into Keystone for each project. Again this too
produces a file that is handed to keystone-manage which will update keystone:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;generate_project_limits&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once the operator sets &lt;cite&gt;quota.enforce_unified_limits = True&lt;/cite&gt;, the Nova DB is
ignored, and limits are accessed from Keystone only.&lt;/p&gt;
&lt;p&gt;To complete the migration, there is an operation to remove all the
DB entries relating to the quota overrides. The tool only works when
&lt;cite&gt;quota.enforce_unified_limits = True&lt;/cite&gt;. It also removes all any per user limits
associated with each project.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt; &lt;span class="n"&gt;remove_db_quota_entries&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note the last two tools allow operators to iterate per project, to limit the
load on the running system. If these tools are used on a running system, it is
recommended that operators don’t change quotas via the API during the
transition.&lt;/p&gt;
&lt;p&gt;The nova status command will warn users that have failed to remove all the
quota information from the DB. This will become an error in the release when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt;&lt;/code&gt; defaults to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is worth noting that the Nova database may contain entries for projects
that have been deleted in keystone. As such, it is advisable to get a list
of active projects from keystone, and only generate_project_limits for those
particular projects.&lt;/p&gt;
&lt;p&gt;This transition leaves several configuration options redundant, in particular
the following will all be deprecated once unified limits is on by default:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.instances&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.cores&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.ram&lt;/span&gt;&lt;/code&gt;: deprecate all these as
the limit now comes from keystone for unified limits, which will default to
unlimited if there is no limit in keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.driver&lt;/span&gt;&lt;/code&gt; is ignored and hard coded to the no-op driver when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.recheck_quota&lt;/span&gt;&lt;/code&gt; will be kept, and will be used in the same
way with unified limits to avoid races when multiple instances are built at
the same time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Ideally we would not add any more proxy APIs, however, operators pushed back
at the Train Forum session, requesting that their tooling continue to work
across the transition. No operators reported using limits other than the
instances, cores and ram limits.&lt;/p&gt;
&lt;p&gt;We could implement hierarchical quotas in isolation, and not adopt unified
limits.&lt;/p&gt;
&lt;p&gt;We could limit the types of resources we limit, but it will be hard to
transition to supporting different kinds of resource limits in a clear
and interoperable way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;See upgrades, no changes in Victora due to having old and new quota systems
side by side. Once we remove the old quota system, we could drop all the
quota related DB tables.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.enforce_unified_limits&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; Nova will proxy the requests
to Keystone’s unified limits API, where possible. The aim will be to keep
horizon functioning correctly during the transition.&lt;/p&gt;
&lt;p&gt;Once using unified limits, operators should move to using Keystone’s
unified limit APIs to set and query limits. Usage information should be
queried via Placement and the Servers API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The removal of quota rechecks for some limits slightly reduces the protection
provided, but really it encourages the proper implementation of API
rate limiting as replacement protection.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Quota errors should appear the same before and after this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;It is possible to have more complicated quota counts with hierarchical
quotas, but the implementation of that is delegated to oslo.limit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;There are several tools to help ease the transition to unified limits noted
above. Although it is expected that use of the feature will help inform the
end direction.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;There will now be two limit system to maintain for a few cycles during the
transition. But this avoids the long term need to maintain complicated
hierarchical limit code, which still getting the advantages, such as being able
to tidy up API policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;To get the best experience, operators need to start using the unified limits
API via Keystone. User should start querying usage from Placement.&lt;/p&gt;
&lt;p&gt;The transition between the existing quota system and unified limits is
detailed in the proposed solution section.&lt;/p&gt;
&lt;p&gt;It is expected that oslo.limit will limit versions of Keystone that can be
used to Queens and newer, which is not expected to affect most users.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;(TBC)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add calls to oslo_limits, guarded by config to enable it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move quota APIs to proxy to Keystone when unified limit quotas enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tools to migrate default and tenant limits from Nova into Keystone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade checks to ensure above tooling is used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/count-quota-usage-from-placement.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keystone manage commands to add limits when keystone API not available&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Grenade test that runs the migration of quota settings (after adding some
quotas).&lt;/p&gt;
&lt;p&gt;Functional tests to ensure quotas are enforced based on unified limits
correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Building on the work to document quota usage from placement, we should
describe how the new system operates. The admin guide needs to detail
how to smoothly migrate to unified limits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Victora&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 01 Jun 2020 00:00:00 </pubDate></item><item><title>Support volume local cache</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/support-volume-local-cache.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-volume-local-cache"&gt;https://blueprints.launchpad.net/nova/+spec/support-volume-local-cache&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to add support of volume local cache in nova. Cache
software such as open-cas &lt;a class="footnote-reference brackets" href="#id12" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; can use fast NVME SSD or persistent memory to
cache for the slow remote volume.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there are different types of fast NVME SSDs, such as Intel Optane
SSD, with latency as low as 10 us. What’s more, persistent memory which aim to
be SSD size but DRAM speed gets popupar now. Typical latency of persistent
memory would be as low as hundreds of nanoseconds. While typical latency of
remote volume for a VM can be at the millisecond level (iscsi / rbd). So these
fast SSDs or persistent memory can be mounted locally on compute nodes and used
as a cache for remote volumes.&lt;/p&gt;
&lt;p&gt;In order to do the cache, there’re some cache software, such as open-cas.
open-cas is very easy to use, you just need to specify a block device as the
cache device, and then can use this device to cache for other block devices.
This is transparent to upper layer and lower layer. Regarding upper layer,
guest don’t know it is using an emulated block device. Regarding lower layer,
backend volume don’t know it is cached, and the data in backend volume will not
have extra change because of cache. That means even if the cache is lost for
some reason, the backend volume can be mounted to other places and available
immediately. This spec is trying to add volume local cache using such cache
software.&lt;/p&gt;
&lt;p&gt;Like all the local cache solution, multi-attach cannot work. This is because
cache on node1 don’t know the changes made to backend volume by node2.&lt;/p&gt;
&lt;p&gt;This feature requires the cache mode “Write-Through”, which makes sure the
cache is fully synced with backend volume all the time. Given this, it is
transparent to live migration. “Write-Through” is also the default cache mode
for open-cas.&lt;/p&gt;
&lt;p&gt;This feature can only cache for backend volumes that would be mounted on host
OS first as block device. So volumes (LibvirtNetVolumeDriver is used) mounted
by QEMU, such as rbd and sheepdog, cannot be cached. Details can be found in
list libvirt_volume_drivers in &lt;a class="footnote-reference brackets" href="#id13" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In some high performance environments, RDMA may be chosen. RDMA effectively
shorten the latency gap between local volume and remote volume. In experimental
environment, without network switch, without read/write io to real volume, the
point to point RDMA network link latency would be even 3 us in best case. This
is the pure network link latency, and this also don’t mean it is faster than
local PCIe, because RDMA NIC card itself in host and target machines also are
PCIe devices. For RDMA scenario, persistent memory is recommended to be
selected as cache device, otherwise may no performance gain.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;User wants to use fast NVME SSD to cache for remote slow volumes. This is
extremely useful for clouds where operators want to boost disk io performance
for specific volumes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;All volumes cached by the same cache instance share same cache mode. The
operator can change cache mode dynamically, using cache software management
tool. os-brick just accepts the cache name and cache IDs from Nova. Cache name
identifies which cache software to use, currently it only supports ‘opencas’.
It is allowed that more than one cache instance in one compute node. Cache IDs
identifies cache instances that can be used. Cache mode is transparent to
os-brick.&lt;/p&gt;
&lt;p&gt;A compute capability is mapped to the trait (e.g. COMPUTE_SUPPORT_VOLUME_CACHE)
and the libvirt driver can set this capability to true if there is cache
instance id is configured in the nove conf. If want the volume be cached,
firstly the volume should belongs to a volume type with “cacheable” property.
Then select the flavor with extra spec containing this trait, so the guest
would be landed at the host machine with cache capability. If don’t want the
volume be cached, just select a flavor without this trait.&lt;/p&gt;
&lt;p&gt;If there’s failure happened during setting up caching, e.g. cache device
broken, then re-schedule the request.&lt;/p&gt;
&lt;p&gt;Final architecture would be something like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                       &lt;span class="n"&gt;Compute&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;

&lt;span class="o"&gt;+---------------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                                                         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                        &lt;span class="o"&gt;+-----+&lt;/span&gt;    &lt;span class="o"&gt;+-----+&lt;/span&gt;    &lt;span class="o"&gt;+-----+&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VM1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VM2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VMn&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                        &lt;span class="o"&gt;+--+--+&lt;/span&gt;    &lt;span class="o"&gt;+--+--+&lt;/span&gt;    &lt;span class="o"&gt;+-----+&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+---------------------------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+---------+&lt;/span&gt;         &lt;span class="o"&gt;+-----+----------+-------------+&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Nova&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="n"&gt;QEMU&lt;/span&gt; &lt;span class="n"&gt;Virtio&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-+-------+&lt;/span&gt;         &lt;span class="o"&gt;+-----+----------+----------+--+&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;detach&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;+-----+----------+------+&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-+-------+&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cas1&lt;/span&gt;  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cas2&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;osbrick&lt;/span&gt; &lt;span class="o"&gt;+---------+&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+---------+&lt;/span&gt; &lt;span class="n"&gt;casadm&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="n"&gt;cas&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                     &lt;span class="o"&gt;+-+---+----------+------+&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;         &lt;span class="n"&gt;Storage&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;              &lt;span class="o"&gt;+--------+&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-----+----+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;rbd&lt;/span&gt;   &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;              &lt;span class="o"&gt;|&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sdd&lt;/span&gt; &lt;span class="o"&gt;+----------+&lt;/span&gt;  &lt;span class="n"&gt;Vol1&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;              &lt;span class="o"&gt;|&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+----------+&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;+-----+-----+&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Vol2&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Fast&lt;/span&gt; &lt;span class="n"&gt;SSD&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-----+----+&lt;/span&gt;   &lt;span class="n"&gt;iscsi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="o"&gt;/...&lt;/span&gt;      &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;+-----------+&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sdc&lt;/span&gt; &lt;span class="o"&gt;+-------------+-------+&lt;/span&gt;  &lt;span class="n"&gt;Vol3&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+----------+&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;                             &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Vol4&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                     &lt;span class="o"&gt;+-----+----+&lt;/span&gt;    &lt;span class="n"&gt;iscsi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt;&lt;span class="o"&gt;/...&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sdb&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------+&lt;/span&gt;  &lt;span class="n"&gt;Vol5&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                     &lt;span class="o"&gt;+----------+&lt;/span&gt;                        &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                                                         &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;.....&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+---------------------------------------------------------+&lt;/span&gt;       &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Changes would include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cache the volume during connecting volume&lt;/p&gt;
&lt;p&gt;In function _connect_volume():&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Check if the volume should be cached or not. Cinder would set the cacheable
property for the volume if caching is allowed. If cacheable is set and
volume_local_cache_driver in CONF is not empty, then do caching. Otherwise
just ignore caching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;attach_cache before attach_encryptor, cache lays under encryptor. It is to
keep encrypted volume secure. No decrypted data would be written to cache
device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call os-brick to cache the volume &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. os-brick will call cache software
to setup the cache. Then replace the path of original volume with the
emulated volume&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova goes ahead to _connect_volume with the newly emulated volume path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If any failure happens during setting up caching, just ignore the failure
and continue the rest code of _connect_volume().&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release cache during disconnecting volume&lt;/p&gt;
&lt;p&gt;In function _disconnect_volume():&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Call os-brick to release the cache for the volume. os-brick will retrieve
the path of original volume from emulated volume, and then replace the path
in connection_info with the original volume path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova goes ahead to _disconnect_volume with the original volume path&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add switch in nova-cpu.conf to enable/disable local cache&lt;/p&gt;
&lt;p&gt;Suggested switch names:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;volume_local_cache_driver: Specifies which cache software to use. Currently
only support ‘opencas’. If it is empty, then local cache is disabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;volume_local_cache_instance_ids: Specifies cache instances that can be
used. Typically opencas has only one cache instance in a single server, but
it has the ability to have more than one cache instances which bind to
different cache device. Nova needs to pass instance IDs to os-brick and let
os-brick to find the best one, e.g. biggest free size, less volumes cached,
etc. All these information can be get from instance ID via cache admin
tool, like casadm.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Suggested section: [compute]. Configuration would be like:
[compute]
volume_local_cache_driver = ‘opencas’
volume_local_cache_instance_ids = 1,15,222&lt;/p&gt;
&lt;p&gt;Instance IDs are separated by commas.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nova calls os-brick to set cache for the volume only when it has the property
of “cacheable” and the flavor requested such caching. Let cinder to determine
and set the property, just like the way did for volume encryption. If the
volume contains property “multiattach”, cinder would not set “cacheable” for
it. Code work flow would be like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;             Nova                                        osbrick


                                              +
         +                                    |
         |                                    |
         v                                    |
   attach_volume                              |
         +                                    |
         |                                    |
         +                                    |
       attach_cache                           |
             +                                |
             |                                |
             +                                |
 +-------+ volume_with_cache_property?        |
 |               +                            |
 | No            | Yes                        |
 |               +                            |
 |     +--+Host_with_cache_capability?        |
 |     |         +                            |
 |     | No      | Yes                        |
 |     |         |                            |
 |     |         +-----------------------------&amp;gt; attach_volume
 |     |                                      |        +
 |     |                                      |        |
 |     |                                      |        +
 |     |                                      |      set_cache_via_casadm
 |     |                                      |        +
 |     |                                      |        |
 |     |                                      |        +
 |     |                                      |      return emulated_dev_path
 |     |                                      |        +
 |     |                                      |        |
 |     |         +-------------------------------------+
 |     |         |                            |
 |     |         v                            |
 |     |   replace_device_path                |
 |     |         +                            |
 |     |         |                            |
 v     v         v                            |
                                              |
attach_encryptor and                          |
rest of attach_volume                         +
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Volume local cache lays upon encryptor would have better performance, but
expose decrypted data in cache device. So based on security consideration,
cache should lay under encryptor in Nova implementation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Code implementation can be found in &lt;a class="footnote-reference brackets" href="#id9" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id10" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id11" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Assign local SSD to a specific VM. VM can then use bcache internally against
the ephemeral disk to cache their volume if they want.&lt;/p&gt;
&lt;p&gt;The drawbacks may include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Can only accelerate one VM. The fast SSD capability cannot be shared by
other VMs. Unlike RAM, SSD normally is in TB level and large enough to
cache for all the VMs in one node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The owner of the VM should setup cache explicitly. But not all the VM owner
want to do this, and not all the VM owner has the knowledge to do this. But
they for sure want the volume performance is better by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a dedicated cache cluster. Mount all the cache (NVME SSD) in cache
cluster as a big cache pool. Then allocate a certain ammount of cache to a
specific volume. The allocated cache can be mounted on compute node through
NVMEof protocol. Then still use cache software to do the same cache.&lt;/p&gt;
&lt;p&gt;But this would be the compete between local PCIe and remote network. The
disadvantage if doing like these ways is: the network of the storage server
would be bottleneck.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Latency) Storage cluster typically provide volume through iscsi/fc
protocol, or through librbd if ceph is used. The latency would be
millisecond level. Even NVME over TCP, the latency would be hundreds of
microsecond, depends on the network topology. As a contrast, the latency of
NVME SSD would be around 10 us, take Intel Optane SSD p4800x as example.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache can be added in backend storage side, e.g. in ceph. Storage server
normally has its own cache mechanism, e.g. using memory as cache, or using
NVME SSD as cache.&lt;/p&gt;
&lt;p&gt;Similiar with above solution, latency is the disadvantage.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Cache software will remove the cached volume data from cache device when
volume is detached. But normally it would not erase the related sectors in
cache device. So in theory the volume data is still in cache device before it
is overwritten. Volume with encryption doesn’t have this security impact if
encryption laying upon volume local cache.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Latency of VM volume will be decreased&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Option volume_local_cache_driver and volume_local_cache_instance_ids should
be set in nova-cpu.conf to enable this feature. Default value of
volume_local_cache_driver would be empty string which means local cache is
disabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This is only for libvirt, other drivers like VMWare, hyperv will not be
changed. This is because open-cas can only support Linux, and libvirt is the
most used one. Meanwhile this spec/implementation would only be tested with
libvirt.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liang Fang &amp;lt;&lt;a class="reference external" href="mailto:liang.a.fang%40intel.com"&gt;liang&lt;span&gt;.&lt;/span&gt;a&lt;span&gt;.&lt;/span&gt;fang&lt;span&gt;@&lt;/span&gt;intel&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gibi&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add COMPUTE_SUPPORT_VOLUME_CACHE trait to os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new compute capability that maps to this trait&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable this capability in the libvirt driver if a caches is configured&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache the volume during connecting volume&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release cache during disconnecting volume&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add switch to enable / disable this feature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit test to be added&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os-brick patch: &lt;a class="footnote-reference brackets" href="#id10" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cinder patch: &lt;a class="footnote-reference brackets" href="#id11" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New unit test should be added&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One of tempest jobs should be changed to enable this feature, with open-cas,
on a vanilla worker image&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This can use open-cas with a local file as NVME device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the emulated volume is created for VM or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the emulated volume is released or not when deleting VM&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One of tempest jobs should be changed to enable this feature, with open-cas,
on a vanilla worker image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Document need to be changed to describe this feature and include the new
options - volume_local_cache_driver, volume_local_cache_instance_ids&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/663542/"&gt;https://review.opendev.org/#/c/663542/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id7"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/663549/"&gt;https://review.opendev.org/#/c/663549/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id6"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/700799/"&gt;https://review.opendev.org/#/c/700799/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://open-cas.github.io/"&gt;https://open-cas.github.io/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/master/nova/virt/libvirt/driver.py"&gt;https://github.com/openstack/nova/blob/master/nova/virt/libvirt/driver.py&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id14"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 18 May 2020 00:00:00 </pubDate></item><item><title>NUMA Topology with Resource Providers</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/numa-topology-with-rps.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/numa-topology-with-rps"&gt;https://blueprints.launchpad.net/nova/+spec/numa-topology-with-rps&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that &lt;a class="reference internal" href="#nested-resource-providers"&gt;Nested Resource Providers&lt;/a&gt; is a thing in both Placement API and
Nova compute nodes, we could use the Resource Providers tree for explaining
the relationship between a root Resource Provider (root RP) ie. a compute node,
and one or more Non-Uniform Memory Access (NUMA) nodes (aka. cells), each of
them having separate resources, like memory or PCI devices.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec only targets to model resource capabilities for NUMA nodes in some
general and quite abstract manner. We won’t address in this spec how we
should model NUMA-affinized hardware like PCI devices or GPUs and will
discuss these relationships in a later spec.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The NUMATopologyFilter checks a number of resources, including emulator threads
policies, CPU pinned instances and memory page sizes. Additionally, it does two
different verifications :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;whether&lt;/em&gt; some host can fit the query because it has enough capacity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;which&lt;/em&gt; resource(s) should be used for this query (eg. which pCPUs or NUMA
node)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With NUMA topologies modeled as Placement resources, those two questions could
be answered by the Placement service as potential allocation candidates that
the filter would &lt;em&gt;only&lt;/em&gt; be responsible for choosing between them in some
very specific cases (eg. PCI device NUMA affinity, CPU pinning and NUMA
anti-affinity).&lt;/p&gt;
&lt;p&gt;Accordingly, we could model the host memory and the CPU topologies as a set of
resource providers arranged in a tree, and just directly allocate resources for
a specific instance from a resource provider subtree representing a NUMA node
and its resources.&lt;/p&gt;
&lt;p&gt;That said, non resource-related features (like &lt;a class="reference internal" href="#choosing-a-specific-cpu-pin-within-a-numa-node-for-a-vcpu"&gt;choosing a specific CPU pin
within a NUMA node for a vCPU&lt;/a&gt;) would still be only done by the virt driver,
and are not covered by this spec.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Consider the following NUMA topology for a “2-NUMA nodes, 4 cores” host with no
Hyper-Threading:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+--------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="n"&gt;CN1&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-+---------------+--+---------------+-+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;NUMA1&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;NUMA2&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+-+----+-+----+-+&lt;/span&gt;  &lt;span class="o"&gt;+-+----+-+----+-+&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU2&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU3&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU4&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="o"&gt;+----+&lt;/span&gt; &lt;span class="o"&gt;+----+&lt;/span&gt;      &lt;span class="o"&gt;+----+&lt;/span&gt; &lt;span class="o"&gt;+----+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here, CPU1 and CPU2 would share the same memory through a common memory
controller, while CPU3 and CPU4 would share their own memory.&lt;/p&gt;
&lt;p&gt;Ideally, applications that require low-latency memory access from multiple
vCPUs on the same instance (for parallel computing reasons) would like to
ensure that those CPU resources are provided by the same NUMA node, or some
performance penalties would occur (if your application is CPU-bound or
I/O-bound of course). For the moment, if you’re an operator, you can use flavor
extra specs to indicate a desired guest NUMA topology for your instance like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor set FLAVOR-NAME \
    --property hw:numa_nodes=FLAVOR-NODES \
    --property hw:numa_cpus.N=FLAVOR-CORES \
    --property hw:numa_mem.N=FLAVOR-MEMORY
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;See all the &lt;a class="reference internal" href="#numa-possible-extra-specs"&gt;NUMA possible extra specs&lt;/a&gt; for a flavor.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The example above is only needed when you want to not evenly divide your
virtual CPUs and memory between NUMA nodes, of course.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Given there are a lot of NUMA concerns, let’s do an iterative approach about
the model we agree.&lt;/p&gt;
&lt;section id="numa-nodes-being-nested-resource-providers"&gt;
&lt;h3&gt;NUMA nodes being nested Resource Providers&lt;/h3&gt;
&lt;p&gt;Given virt drivers can amend a provider tree given by the compute node
ResourceTracker, then the libvirt driver could create child providers for each
of the 2 sockets representing separate NUMA node.&lt;/p&gt;
&lt;p&gt;Since CPU resources are tied to a specific NUMA node, it makes sense to model
the corresponding resource classes as part of the child NUMA Resource
Providers. In order to facilitate querying NUMA resources, we propose to
decorate the NUMA child resource providers with a specific trait named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NUMA_ROOT&lt;/span&gt;&lt;/code&gt; that would be on each NUMA &lt;em&gt;node&lt;/em&gt;. That would help to know
which hosts would be &lt;em&gt;NUMA-aware&lt;/em&gt; and which others are not.&lt;/p&gt;
&lt;p&gt;Memory is a bit tougher to represent. The granularity of a NUMA node having
an amount of attached memory is somehow a first approach but we’re missing the
point that the smallest allocatable unit you can assign with Nova is
really a page size. Accordingly, we should rather model our NUMA subtree
with children Resource Providers that represent the smallest unit of memory
you can allocate, ie. a page size. Since a pagesize is not a &lt;em&gt;consumable&lt;/em&gt;
amount but rather a &lt;em&gt;qualitative&lt;/em&gt; information that helps us to allocate
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; resources, we propose three traits :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;&lt;/code&gt; would allow us to
know whether the memory page size is default or optionally configured.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_MEMORY_PAGE_SIZE_&amp;lt;X&amp;gt;&lt;/span&gt;&lt;/code&gt; where &amp;lt;X&amp;gt; is an integer would allow us to
know the size of the page in KB. To make it clear, even if the trait is a
custom one, it’s important to have a naming convention for it so the
scheduler could ask about page sizes without knowing all the traits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                                &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
                                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CN_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;
                                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;DISK_GB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
                                &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
                                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
                                &lt;span class="o"&gt;+--+---------------------------++&lt;/span&gt;
                                   &lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;
                                   &lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;+-------------------------+&lt;/span&gt;                   &lt;span class="o"&gt;+--------------------------+&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NUMA_NODE_O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NUMA_NODE_1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;+-------------------------+&lt;/span&gt;                   &lt;span class="o"&gt;+--------------------------+&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;+-------------------+-----+&lt;/span&gt;                   &lt;span class="o"&gt;+--------------------------+&lt;/span&gt;
              &lt;span class="o"&gt;/&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;    \                                          &lt;span class="o"&gt;/+&lt;/span&gt;\
              &lt;span class="o"&gt;+&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;     \&lt;span class="n"&gt;_____________________________&lt;/span&gt;          &lt;span class="o"&gt;.......&lt;/span&gt;
              &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                   \
&lt;span class="o"&gt;+-------------+-----------+&lt;/span&gt;   &lt;span class="o"&gt;+-+--------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RP_UUID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RP_UUID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RP_UUID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10240&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_4&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_2048&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_1048576&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As we said above, we don’t want to support children PCI devices for Ussuri
at the moment. Other current children RPs for a root compute node, like
ones for VGPU resources or bandwidth resources would still have their
parent be the compute node.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="numa-rp"&gt;
&lt;h3&gt;NUMA RP&lt;/h3&gt;
&lt;p&gt;Resource Provider names for NUMA nodes shall follow a convention of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nodename_NUMA#&lt;/span&gt;&lt;/code&gt; where nodename would be the hypervisor hostname (given by
the virt driver) and where NUMA# would literally be a string made of ‘NUMA’
postfixed by the NUMA cell ID which is provided by the virt driver.&lt;/p&gt;
&lt;p&gt;Each NUMA node would be then a child Resource Provider, having two resource
classes :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;: for telling how many virtual cores (not able to be pinned) the NUMA
node has.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;: for telling how many possible pinned cores the NUMA node has.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A specific trait should be decorating it as we explained : &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NUMA_ROOT&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="memory-pagesize-rp"&gt;
&lt;h3&gt;Memory pagesize RP&lt;/h3&gt;
&lt;p&gt;Each &lt;a class="reference internal" href="#numa-rp"&gt;NUMA RP&lt;/a&gt; should have child RPs for each possible memory page
size per host, and having a single resource class :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt;: for telling how much memory the NUMA node has in that specific
page size.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This RP would be decorated by two traits :&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;&lt;/code&gt; (default if not configured) or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;&lt;/code&gt; (if large pages are configured)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the size of the page size : CUSTOM_MEMORY_PAGE_SIZE_# (where # is the size
in KB - default to 4 as the kernel defaults to 4KB page sizes)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="compute-node-rp"&gt;
&lt;h3&gt;Compute node RP&lt;/h3&gt;
&lt;p&gt;The root Resource Provider (ie. the compute node) would only provide resources
for classes that are not NUMA-related. Existing children RPs for vGPUs or
bandwidth-aware resources should still have this parent (until we discuss
about NUMA affinity for PCI devices).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="optionally-configured-numa-resources"&gt;
&lt;h3&gt;Optionally configured NUMA resources&lt;/h3&gt;
&lt;p&gt;Given there are NUMA workloads but also non-NUMA workloads, it’s also important
for operators to just have compute nodes accepting the latter.
That said, having the compute node resources to be split between multiple
NUMA nodes could be a problem for those non-NUMA workloads if they want to keep
the existing behaviour.&lt;/p&gt;
&lt;p&gt;For example, say an instance with 2 vCPUs and one host having 2 NUMA nodes but
each one only accepting one VCPU, then the Placement API wouldn’t accept that
host (given each nested RP only accepts one VCPU). For that reason, we need to
have a configuration for saying which resources should be nested.
To reinforce the above, that means a host would be either NUMA or non-NUMA,
hence non-NUMA workloads being set on a specific NUMA node if host is set so.
The proposal we make here will be :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enable_numa_reporting_to_placement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Ussuri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For below, we will tell hosts as “NUMA-aware” ones that have this option be
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;. For hosts that have this option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; they are explicitely
asked to have a legacy behaviour and will be called “non-NUMA-aware”.&lt;/p&gt;
&lt;p&gt;Depending on the value of the option, Placement would accept or not a host
for the according request. The resulting matrix can be:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+----------------------------------------+----------+-----------+----------+
| ``enable_numa_reporting_to_placement`` | ``None`` | ``False`` | ``True`` |
+========================================+==========+===========+==========+
| NUMA-aware flavors                     | Yes      | No        | Yes      |
+----------------------------------------+----------+-----------+----------+
| NUMA-agnostic flavors                  | Yes      | Yes       | No       |
+----------------------------------------+----------+-----------+----------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Yes&lt;/span&gt;&lt;/code&gt; means that there could be allocation candidates from this host,
while &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;No&lt;/span&gt;&lt;/code&gt; means that no allocation candidates will be returned.&lt;/p&gt;
&lt;p&gt;In order to distinghish compute nodes that have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; value instead of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, we will decorate the former with a specific trait name
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NON_NUMA&lt;/span&gt;&lt;/code&gt;. Accordingly, we will query Placement by adding this forbidden
trait for &lt;em&gt;not&lt;/em&gt; getting nodes that operators explicitly don’t want them to
support NUMA-aware flavors.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;By default, the value for that configuration option will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; for
upgrade reasons. By the Ussuri timeframe, operators will have to decide
which hosts they want to support NUMA-aware instances and which should be
dedicated for ‘non-NUMA-aware’ instances. A &lt;cite&gt;nova-status pre-upgrade check&lt;/cite&gt;
command will be provided that will warn them to decide before upgrading to
Victoria, if the default value is about to change as we could decide later
in this cycle. Once we stop supporting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; (in Victoria or later), the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NON_NUMA&lt;/span&gt;&lt;/code&gt; trait would no longer be needed so we could stop querying
it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since we allow a transition period for helping the operators to decide, we
will also make clear that this is a one-way change and that we won’t
provide a backwards support for turning a NUMA-aware host into a
non-NUMA-aware host.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade impact&lt;/a&gt; section for further details.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since the discovery of a NUMA topology is made by virt drivers, it
makes the population of those nested Resource Providers to necessarly
be done by each virt driver. Consequently, while the above
configuration option is said to be generic, the use of this option
for populating the Resource Providers tree will only be done by
the virt drivers. Of course, a shared module could be imagined for
the sake of consistency between drivers, but this is an
implementation detail.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="the-very-simple-case-i-don-t-care-about-a-numa-aware-instance"&gt;
&lt;h3&gt;The very simple case: I don’t care about a NUMA-aware instance&lt;/h3&gt;
&lt;p&gt;For flavors just asking for, say, vCPUs and memory without asking them to be
NUMA-aware, then we will make a single Placement call asking to &lt;em&gt;not&lt;/em&gt; land
them on a NUMA-aware host:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;resources=VCPU:&amp;lt;X&amp;gt;,MEMORY_MB=&amp;lt;Y&amp;gt;
&amp;amp;required=!HW_NUMA_ROOT
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case, even if NUMA-aware hosts have enough resources for this query,
the Placement API won’t provide them but only non-NUMA-aware ones (given the
forbidden &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NUMA_ROOT&lt;/span&gt;&lt;/code&gt; trait).
We’re giving the possibility to the operator to shard their clouds between
NUMA-aware hosts and non-NUMA-aware hosts but that’s not really changing the
current behaviour as of now where operators create aggregates to make sure
non-NUMA-aware instances can’t land on NUMA-aware hosts.&lt;/p&gt;
&lt;p&gt;See the &lt;cite&gt;Upgrade impact&lt;/cite&gt; session for rolling upgrade situations where clouds
are partially upgraded to Ussuri and where only a very few nodes are reshaped.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="asking-for-numa-aware-vcpus"&gt;
&lt;h3&gt;Asking for NUMA-aware vCPUs&lt;/h3&gt;
&lt;p&gt;As NUMA-aware hosts have a specific topology with memory being in a grand-child
RP, we basically need to ensure we can translate the existing expressiveness in
the flavor extra specs into a Placement allocation candidates query that asks
for parenting between the NUMA RP containing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources and the
memory pagesize RP containing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; resources.&lt;/p&gt;
&lt;p&gt;Accordingly, here are some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt; as a value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_policy&lt;/span&gt;&lt;/code&gt; which means that in this
example, allocation candidates can all be from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROC1&lt;/span&gt;&lt;/code&gt; group meaning
that we defeat the purpose of having the resources separated into different
NUMA nodes (which is the purpose of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&lt;/span&gt;&lt;/code&gt;). This is OK
as we will also modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; to only accept
allocation candidates for a host that are in different NUMA nodes.
It will probably be implemented in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.hardware&lt;/span&gt;&lt;/code&gt; module but
that’s an implementation detail.&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=1&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&amp;amp;hw:numa_cpus.0=0,1&amp;amp;hw:numa_cpus.1=2,3,4,5,6,7&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&amp;amp;hw:numa_cpus.0=0,1&amp;amp;hw:numa_mem.0=1024&lt;/span&gt;
&lt;span class="pre"&gt;&amp;amp;hw:numa_cpus.1=2,3,4,5,6,7&amp;amp;hw:numa_mem.1=7168&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7168&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can understand, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; values will be a result
of the division of respectively the flavored vCPUs and the flavored memory by
the value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes&lt;/span&gt;&lt;/code&gt; (which is actually already calculated and
provided as NUMATopology object information in the RequestSpec object).&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The translation mechanism from a flavor-based request into Placement query
will be handled by the scheduler service.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since memory is provided as grand-child, we need to always ask for a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;&lt;/code&gt; which is the default.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="asking-for-specific-memory-page-sizes"&gt;
&lt;h3&gt;Asking for specific memory page sizes&lt;/h3&gt;
&lt;p&gt;Operators defining a flavor of 2 vCPUs, 4GB of RAM and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=2MB,hw:numa_nodes=2&lt;/span&gt;&lt;/code&gt; will see that the Placement query will
become:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you only want large page size support without really specifying which size
(eg. by specifying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=large&lt;/span&gt;&lt;/code&gt; instead of, say, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;2MB&lt;/span&gt;&lt;/code&gt;), then
the above same request for large pages would translate into:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Asking the same with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=small&lt;/span&gt;&lt;/code&gt; would translate into:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And eventually, asking with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=any&lt;/span&gt;&lt;/code&gt; would mean:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As we said for vCPUs, given we query with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_policy=none&lt;/span&gt;&lt;/code&gt;,
allocation candidates would be within the same NUMA node but that’s fine
since we also said that the scheduler filter would then no agree with
them if there is a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=X&lt;/span&gt;&lt;/code&gt; there.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="the-fallback-case-for-numa-aware-flavors"&gt;
&lt;h3&gt;The fallback case for NUMA-aware flavors&lt;/h3&gt;
&lt;p&gt;In the &lt;a class="reference internal" href="#optionally-configured-numa-resources"&gt;Optionally configured NUMA resources&lt;/a&gt; section, we said that we would
want to accept NUMA-aware flavors to land on hosts that have the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_numa_reporting_to_placement&lt;/span&gt;&lt;/code&gt; option set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;. Since we can’t
yet build a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OR&lt;/span&gt;&lt;/code&gt; query for allocation candidates, we propose to make another
call to Placement.
In this specific call (we name it a fallback call), we want to get all
non-reshaped nodes that are &lt;em&gt;not&lt;/em&gt; explicitly said to not support NUMA.
In this case, the request is fairly trivial since we decorated them with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NON_NUMA&lt;/span&gt;&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;resources=VCPU:&amp;lt;X&amp;gt;,MEMORY_MB=&amp;lt;Y&amp;gt;
&amp;amp;required=!HW_NON_NUMA,!HW_NUMA_ROOT
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then we would get all compute nodes that have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; value (
including nodes that are still running the Train release in a rolling upgrade
fashion).&lt;/p&gt;
&lt;p&gt;Of course, we would get nodes that could potentially &lt;em&gt;not&lt;/em&gt; accept the
NUMA-aware flavor but we rely on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; for not selecting
them, exactly like what we do in Train.&lt;/p&gt;
&lt;p&gt;There is some open question about whether we should do the fallback call only
if the NUMA-specific call is not getting candidates or if we should generate
the two calls either way and merge the results.
The former is better for performance reasons since we avoid a potentially
unnecessary call but would generate some potential spread/pack affinity issues.
Here we all agree on the fact we can leave the question unresolved for now and
defer the resolution to the implementation phase.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Modeling of NUMA resources could be done by using specific NUMA resource
classes, like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMA_VCPU&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMA_MEMORY_MB&lt;/span&gt;&lt;/code&gt; that would only be set for
children NUMA resource providers, and where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; resource
classes would only be set on the root Resource Provider (here the compute
node).&lt;/p&gt;
&lt;p&gt;If the Placement allocations candidates API was also able to provide a way to
say ‘you can split the resources between resource providers’, we wouldn’t need
to carry a specific configuration option for a long time. All hosts would then
be reshaped to be NUMA-aware but then non-NUMA-aware instances could
potentially land on those hosts. That wouldn’t change the fact that for
optimal capacity, operators need to shard their clouds between NUMA workloads
and non-NUMA ones, but from a Placement perspective, all hosts would be equal.
This alternative proposal has largely already been discussed in a
spec but the outcome consensus was that it was very
difficult to implement and potentially not worth the difficulty.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None, flavors won’t need to be modified since we will provide a translation
mechanism. That said, we will explicitly explain in the documentation that
we won’t support any placement-like extra specs in flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Only when changing the configuration option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, a reshape is done.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators would want to migrate some instances from hosts to anothers before
explicitely enabling or disabling NUMA awareness on their nodes since they will
have to consider the capacity usage accordingly as they will have to shard
their cloud. This being said, this would only be necessary for clouds that
weren’t yet already dividing NUMA-aware and non-NUMA-aware workloads between
hosts thru aggregates.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None, except virt driver maintainers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As described above, in order to prevent a flavor update during upgrade, we will
provide a translation mechanism that will take the existing
flavor extra spec properties and transform them into Placement numbered groups
query.&lt;/p&gt;
&lt;p&gt;Since there will be a configuration option for telling that a host would become
NUMA-aware, the corresponding allocations accordingly have to change hence the
virt drivers be responsible for providing a reshape mechanism that will
eventually call the &lt;a class="reference internal" href="#placement-api-reshaper-endpoint"&gt;Placement API /reshaper endpoint&lt;/a&gt; when starting the
compute service. This reshape implementation will absolutely need to consider
the Fast Forward Upgrade (FFU) strategy where all controlplane is down and
should possibly document any extra step required for FFU with an eventual
removal in a couple of releases once all deployers no longer need this support.&lt;/p&gt;
&lt;p&gt;Last but not the least, we will provide a transition period (at least during
the Ussuri timeframe) where operators can decide which hosts to dedicate to
NUMA-aware workloads. A specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt; &lt;span class="pre"&gt;pre-upgrade&lt;/span&gt; &lt;span class="pre"&gt;check&lt;/span&gt;&lt;/code&gt; command
will warn them to do so before upgrading to Victoria.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bauzas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;bauzas&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;libvirt driver passing NUMA topology through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hyper-V driver passing NUMA topology through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Possible work on the NUMATopologyFilter to look at the candidates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler translating flavor extra specs for NUMA properties into Placement
queries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt; &lt;span class="pre"&gt;pre-upgrade&lt;/span&gt; &lt;span class="pre"&gt;check&lt;/span&gt;&lt;/code&gt; command&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional tests and unittests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="nested-resource-providers"&gt;Nested Resource Providers&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/approved/nested-resource-providers.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/queens/approved/nested-resource-providers.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="choosing-a-specific-cpu-pin-within-a-numa-node-for-a-vcpu"&gt;choosing a specific CPU pin within a NUMA node for a vCPU&lt;/span&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/cpu-topologies.html#customizing-instance-cpu-pinning-policies"&gt;https://docs.openstack.org/nova/latest/admin/cpu-topologies.html#customizing-instance-cpu-pinning-policies&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="numa-possible-extra-specs"&gt;NUMA possible extra specs&lt;/span&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/flavors.html#extra-specs-numa-topology"&gt;https://docs.openstack.org/nova/latest/admin/flavors.html#extra-specs-numa-topology&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="huge-pages"&gt;Huge pages&lt;/span&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;https://docs.openstack.org/nova/latest/admin/huge-pages.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="placement-api-reshaper-endpoint"&gt;Placement API /reshaper endpoint&lt;/span&gt;: &lt;a class="reference external" href="https://developer.openstack.org/api-ref/placement/?expanded=id84-detail#reshaper"&gt;https://developer.openstack.org/api-ref/placement/?expanded=id84-detail#reshaper&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="placement-can-split"&gt;Placement can_split&lt;/span&gt;: &lt;a class="reference external" href="https://review.opendev.org/#/c/658510/"&gt;https://review.opendev.org/#/c/658510/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="physical-cpu-resources"&gt;physical CPU resources&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 14 May 2020 00:00:00 </pubDate></item><item><title>Add a nova-audit service for periodic maintenance</title><link>https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/nova-audit.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-audit"&gt;https://blueprints.launchpad.net/nova/+spec/nova-audit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova is a distributed system, which means that things fail in strange
ways and data stored across multiple systems gets out of sync with the
actual state of reality. Hosts and instances come and go, along with
network connectivity, the message bus and database. Recently we have
gained a number of “heal $thing” routines that operators can run
either periodically or on demand to synchronize the states of various
services and data stores to resolve or prevent problems. The number of
these tasks is already overwhelming for the average operator, and
tracking new tasks each cycle is not realistic &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As described above, we have an increasing number of maintenance tasks
that need to be run in various scenarios. In most cases, these tasks
are idempotent and safe to run even when nothing is wrong. Operators
need a single mechanism for performing these maintenance tasks and
healing activities that can be run periodically in the background with
minimal impact to runtime performance, other than to hopefully fix
problems related to inconsistencies before they become acute enough to
get an human involved.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I would like Nova to heal itself whenever possible to
minimize the number of support incidents requiring human intervention.&lt;/p&gt;
&lt;p&gt;As a user, I would like Nova to heal itself whenever possible to avoid
having to involve support for transient issues, which may be
impossible or expensive, especially during off-hour periods.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We already have a number of these maintenance activities codified in
one-shot commands &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; that can be run on-demand once a problem has been
identified. Since most of them are not harmful or overly expensive, we
should be able to run those things periodically to attempt to fix
problems automatically before the operator gets involved.&lt;/p&gt;
&lt;p&gt;This spec proposes a new binary called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt; to encapsulate
these tasks. Ideally it should be usable in multiple ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a singleton daemon that periodically runs tasks at various
intervals according to their potential impact on the system and
need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a one-shot “fix stuff” command that can be run from cron or
otherwise scheduled or executed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a daemon or one-shot command that purely audits potential
problems, but makes no changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new config section of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[audit]&lt;/span&gt;&lt;/code&gt; would be added with timers and
default values for each task.&lt;/p&gt;
&lt;p&gt;Current heal/sync/fix/cleanup tasks we have that could be integrated:&lt;/p&gt;
&lt;section id="heal-allocations"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_allocations&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks the consistency of allocations in Placement for
instances in Nova. It has a runtime performance impact on both
Placement and the Nova database. Many instances means this should
probably check one instance per cycle, but potentially a short cycle
time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="audit-allocations"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;audit_allocations&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks for orphaned allocations in Placement for instances in
Nova and will delete them if specified by the configuration.
It has a runtime performance impact on both Placement and the Nova
database. Many instances means this should probably check one instance
per cycle, but potentially a short cycle time.&lt;/p&gt;
&lt;p&gt;Today, the command is named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;placement&lt;/span&gt; &lt;span class="pre"&gt;audit&lt;/span&gt;&lt;/code&gt; but it
might be a good idea to name it more specifically inside the context of
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt; command and service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="sync-aggregates"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sync_aggregates&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks that host aggregates match between Nova and
Placement. It is required for some scheduler activities, but not all
cases. It has a runtime performance impact on both Placement and the
Nova database. Many hosts means this should probably check one
aggregate per cycle. Aggregates generally change infrequently, so a
long cycle time of an hour or more is probably reasonable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="map-instances"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;map_instances&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task checks that instances have a suitable mapping to a cell. It
has a runtime performance impact on the Nova database. Many instances
means this should probably check one instance per cycle, with a
relatively short cycle time. It may also be better to check one cell
at a time, very infrequently such as once per day.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="discover-hosts"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;discover_hosts&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task ensures that newly-registered hypervisor hosts are mapped to
the appropriate cell. This has a runtime impact on the Nova database,
but there is an efficient way to query for unmapped hosts, so this can
run relatively frequently, such as every ten minutes.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;There is already a mechanism by which to run this
periodically in the scheduler service, which should be
deprecated and replaced by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="archive-deleted-rows"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task archives deleted data from the main database tables into the
shadow tables. It has a runtime performance impact on the Nova
database, both negative (while running) and positive (after
running). Some people never run this, so a cycle time of once per day
or week should be fine. This also needs a parameter to limit the scope
of archived changes to a date range, defaulting to some multiple of
the cycle time.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This (and others) may need a configuration element to
control its execution only between certain hours or days.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="purge"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;purge&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This task removes data from the shadow tables entirely. It has a
runtime performance impact on the Nova database, but it is just
deleting data from tables accessed only during the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt; operation. In reality, this should probably
be run directly after the archival process, potentially with a
different age scope.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="heal-instance-mappings-proposed"&gt;
&lt;h3&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_instance_mappings&lt;/span&gt;&lt;/code&gt; (proposed)&lt;/h3&gt;
&lt;p&gt;This task scans for orphaned instance mappings in the API database
that have no build request or matching instance in a cell. It has a
runtime performance impact on the Nova API and cell databases, but
only looks for mappings with no cell id. It is bounded by the number
of in-flight instance builds plus the number of orphans, which should
be small. Thus it should be fine to run this relatively frequently,
such as every ten minutes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could obviously do nothing. People are managing the complexity
today, so we could simply choose to let them continue.&lt;/p&gt;
&lt;p&gt;We could eliminate the daemon and scheduling nature of the proposal
and just provide a very unified interface to running these commands –
a single place to find all the periodic maintenance tasks separate
from the setup sort of things that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;We could integrate this into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; itself, under a
“maintenance” subcommand or similar.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None. You could argue that notifications sent about audit activity
would be useful, but doing so would require more setup and
configuration of this utility, as well as connectivity and credentials
to the message bus. We could implement that later if there is a need.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be some runtime performance impact due to the background
nature of the audit and any cleanup that happens. Mitigation is to not
run it, tune the intervals to be longer, or run it in single-shot mode
when desired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will have to learn about and deploy a new
command/service. This will hopefully be completely offeset by the
reduced complexity of managing and maintaining Nova in the longer
term.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New maintenance tasks that are added will need to be done in an
idempotent and efficient way and according to whatever interface for
these commands is defined.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;A new binary will be added, which will have some impact on
upgrades. Any existing periodic maintenance jobs that call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;
for various tasks will need to convert over to the new command. The
interfaces we have for existing things in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; can be
deprecated but maintained for an extended period to avoid breaking
existing deployments.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Specific tasks like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt; may make
sense to continue to exist in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt; as well.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt; command and define scheduling
mechanisms and internal interfaces.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the new config section and items.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement connectors to integrate the existing tasks we have into
the new command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-next&lt;/span&gt;&lt;/code&gt; job to run the audit command in single-shot
mode after the tempest run, ideally removing the existing
archive/purge invocation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional testing of the daemon and internal architecture,
and the continued requirement for testing of the actual tasks.  A
single-shot run in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-next&lt;/span&gt;&lt;/code&gt; job as we currently do today for
archive/purge.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operator documentation about the new command, how to deploy it, and
per-knob documentation about the impacts and suggested intervals.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Proposed new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_instance_mappings&lt;/span&gt;&lt;/code&gt; command for Ussuri: &lt;a class="reference external" href="https://review.opendev.org/#/c/655908/"&gt;https://review.opendev.org/#/c/655908/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Commands in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/cli/nova-manage.html"&gt;https://docs.openstack.org/nova/latest/cli/nova-manage.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Victoria&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed and added the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;audit_allocations&lt;/span&gt;&lt;/code&gt; task to include
the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;placement&lt;/span&gt; &lt;span class="pre"&gt;audit&lt;/span&gt;&lt;/code&gt; functionality in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-audit&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 29 Apr 2020 00:00:00 </pubDate></item><item><title>Add action event fault details</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/action-event-fault-details.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/action-event-fault-details"&gt;https://blueprints.launchpad.net/nova/+spec/action-event-fault-details&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The blueprint proposes to add the fault details to the failed instance
action event.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, the instance action event details that a non-admin owner of a
server sees do not contain any useful information about what caused the
failure of the action. For example, if we failed to cold migrate a server,
show the server’s event info by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt; &lt;span class="pre"&gt;event&lt;/span&gt; &lt;span class="pre"&gt;show&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;server&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;request-id&amp;gt;&lt;/span&gt;&lt;/code&gt; that will be
recorded as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"finish_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:27.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"start_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:26.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cold_migrate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error"&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"finish_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:27.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"start_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:26.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"conductor_migrate_server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error"&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Obviously, from the response of the server event action, the user cannot
obtain the actual useful information.&lt;/p&gt;
&lt;p&gt;If the server status is not &lt;strong&gt;ERROR&lt;/strong&gt; but some operation failed, the user
cannot get the fault details either because &lt;a class="reference external" href="https://docs.openstack.org/api-guide/compute/faults.html#instance-faults"&gt;server faults&lt;/a&gt; are only shown
for servers in &lt;strong&gt;ERROR&lt;/strong&gt; or &lt;strong&gt;DELETED&lt;/strong&gt; status. But instance actions can be
shown for a server in any status (and even for deleted servers since
microversion 2.21).&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a non-admin user, I would like to know the details about the failure when
the server is not in &lt;strong&gt;ERROR&lt;/strong&gt; status. Although I can’t see the exact
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traceback&lt;/span&gt;&lt;/code&gt;, at least I can do other attempts based on the details.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In a new microversion, expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt; field in the Show Server
Action Details API:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-instance-actions/{request_id}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Add a new policy to control the visibility for a set of instance action
attributes, its default rule is ‘rule:system_reader_api’ (Legacy rule
is ‘rule:admin_api’).&lt;/p&gt;
&lt;p&gt;The event “details” are the same as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fault.message&lt;/span&gt;&lt;/code&gt; that the user would
see when the server is in &lt;strong&gt;ERROR&lt;/strong&gt; status. For NovaExceptions that would be
the actual exception message but for non-NovaExceptions it’s just the
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/56fc3f28e48bd9c6faf72d2a8bfdf520cc3e60d0/nova/compute/utils.py#100"&gt;exception class name&lt;/a&gt; (In the defined &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;exception_to_dict&lt;/span&gt;&lt;/code&gt; function to do
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;fault.__class__.__name__&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_message&lt;/span&gt;&lt;/code&gt; field on NovaException which, if present, gets percolated
up to a new field similar to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt;. Perhaps this can be as painful
as documenting all the different error types.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt; column was already in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_actions_events&lt;/span&gt;&lt;/code&gt;
table, and it’s a TEXT size column so it should be large enough to hold
exception fault messages.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;In a new microversion, expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt; parameters in the following
API responses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/os-instance-actions/{request_id}&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"finish_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:27.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"start_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:26.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cold_migrate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No valid host was found."&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"finish_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:27.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"start_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-11-13T16:18:26.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"conductor_migrate_server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No valid host was found."&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This only populates the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt; attribute after checking
that the policy matches ‘rule: system_reader_api’.&lt;/p&gt;
&lt;p&gt;With the new microversion the “details” key is always returned with each
event dict but the value may be null because of old records or events that
did not fail.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There is a chance for a security impact with this change because we could be
leaking sensitive information about the deployment to a non-admin end user,
but we already do through server faults so this shouldn’t be &lt;em&gt;worse&lt;/em&gt;.
Note &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1851587"&gt;bug 1851587&lt;/a&gt; about faults.&lt;/p&gt;
&lt;p&gt;Add a new policy so that the deployer can decide whether to expose these
fault information to the end users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The developers have to be careful about what information they put into
NovaExceptions which could leak sensitive information to a non-admin end user.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None. The new column in the database was already exist.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brinzhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt; to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionEvent&lt;/span&gt;&lt;/code&gt; object, and populating it,
and the populating part requires some work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the API to expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;details&lt;/span&gt;&lt;/code&gt; field in GET responses that expose
instance action event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test for negative scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test (API samples).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary for this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the API reference for the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;[1] “Thoughts on exposing exception type to non-admins in instance action&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;event” in ML
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-November/010775.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2019-November/010775.html&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Track user_id/project_id for migrations</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/add-user-id-field-to-the-migrations-table.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/add-user-id-field-to-the-migrations-table"&gt;https://blueprints.launchpad.net/nova/+spec/add-user-id-field-to-the-migrations-table&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The blueprint proposes tracking the user_id and project_id of the user that
initiated a server migration and exposing those values in the API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;By default, all server actions which create a migration record (live migration,
cold migration, resize, evacuate) except resize are initiated by an admin who
might not own the server. There could be multiple users within the same admin
project who migrate (or evacuate) servers. The migrations APIs do not expose
information about who actually migrated the server which is important for
auditing. The instance actions API does record the initiating user/project
but trying to correlate the instance actions to the migrations can be
complicated and error prone, especially if multiple migrations occur on the
same server in the same day.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an (admin) user, I would like to know who operates the instance through the
instance migration history without having to try and stitch that information
together from the migrations and instance actions APIs.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;When creating a Migration record, store the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt;
from the request context, similar to an InstanceAction record.&lt;/p&gt;
&lt;p&gt;In a new microversion, expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; fields in the
following APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-migrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/migrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/migrations/{migration_id}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-migrations&lt;/span&gt;&lt;/code&gt; request will add optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; query parameters for filtering migrations by user or
project.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;As noted above, each operation that generates a migration record will also
have an instance action and the instance action records the user_id and
project_id of who made the request. However, there is no other direct link
between the instance action record and the migration record so trying to use
the actions to correlate that information to the migrations can be complicated
and error prone, especially if a server is moved multiple times in the same
day. Since migration records are a top-level resource in the API like servers,
it makes sense for them to include the user_id/project_id like servers when
they are created and by whom.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; columns to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrations&lt;/span&gt;&lt;/code&gt; table. The
schema will be the same as in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_actions&lt;/span&gt;&lt;/code&gt;
tables:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The columns will be nullable since existing records would not have values for
those columns.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;In a new microversion, expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; parameters
in the following API responses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET /os-migrations&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"migrations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-29T13:42:02.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"dest_compute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"dest_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2.3.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"dest_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"instance_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8600d31b-d1a1-4632-b2ff-45c2be1a70ff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"new_instance_type_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"old_instance_type_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"source_compute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"source_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"done"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-29T13:42:02.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"migration_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"migration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"42341d4b-346a-40d0-83c6-5f4f6892b650"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ef9d34b4-45d0-4530-871b-3fb535988394"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"project_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"011ee9f4-8f16-4c38-8633-a254d420fd54"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/migrations&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"migrations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2016-01-29T13:42:02.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"dest_compute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"dest_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2.3.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"dest_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"server_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4cfba335-03d8-49b2-8c52-e69043d1e8fe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"source_compute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"source_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"running"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"memory_total_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"memory_processed_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"memory_remaining_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;111111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"disk_total_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;234567&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"disk_processed_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"disk_remaining_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;211111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2016-01-29T13:42:02.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12341d4b-346a-40d0-83c6-5f4f6892b650"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ef9d34b4-45d0-4530-871b-3fb535988394"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"project_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"011ee9f4-8f16-4c38-8633-a254d420fd54"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /servers/{server_id}/migrations/{migration_id}&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"migration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2016-01-29T13:42:02.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"dest_compute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"dest_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2.3.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"dest_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"server_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4cfba335-03d8-49b2-8c52-e69043d1e8fe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_compute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compute1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"running"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"memory_total_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"memory_processed_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"memory_remaining_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;111111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"disk_total_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;234567&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"disk_processed_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"disk_remaining_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;211111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2016-01-29T13:42:02.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12341d4b-346a-40d0-83c6-5f4f6892b650"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ef9d34b4-45d0-4530-871b-3fb535988394"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"project_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"011ee9f4-8f16-4c38-8633-a254d420fd54"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key will always be returned but the value could be null for older records.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-migrations&lt;/span&gt;&lt;/code&gt; API will also have optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; query parameters for filtering migrations by user and/or
project:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /os-migrations?user_id=ef9d34b4-45d0-4530-871b-3fb535988394

GET /os-migrations?project_id=011ee9f4-8f16-4c38-8633-a254d420fd54

GET /os-migrations?user_id=ef9d34b4-45d0-4530-871b-3fb535988394&amp;amp;project_id=011ee9f4-8f16-4c38-8633-a254d420fd54
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceActionPayload&lt;/span&gt;&lt;/code&gt; already contains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;action_initiator_user&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;action_initiator_project&lt;/span&gt;&lt;/code&gt; fields.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Update python-novaclient for the new microversion (and python-openstackclient
if it grows server migration resource CLIs in the future).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None. The new columns in the database will be nullable as will the fields
on the Migration object and the API response can return null values. A data
migration to populate the values for existing migrations will not be added.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Brin Zhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mriedem&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrations&lt;/span&gt;&lt;/code&gt; table and
Migration versioned object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the API to expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; fields in
GET responses that expose migration resources. Also add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; query parameters to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-migrations&lt;/span&gt;&lt;/code&gt; for filtering
the results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test for negative scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test (API samples).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary for this change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the API reference for the new microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Cross-cell resize</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/cross-cell-resize.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cross-cell-resize"&gt;https://blueprints.launchpad.net/nova/+spec/cross-cell-resize&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Expand resize (cold migration) support across multiple cells.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Multi-cell support was added to the controller services (API, conductor,
scheduler) in the Pike release. However, server move operations, like resize,
are restricted to the cell in which the instance currently lives. Since
it is common for deployments to shard cells by hardware types, and therefore
flavors isolated to that hardware, the inability to resize across cells is
problematic when a deployment wants to move workloads off the old hardware
(flavors) and onto new hardware.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a large multi-cell deployment which shards cells by hardware generation,
I want to decommission old hardware in older cells and have new and existing
servers move to newer cells running newer hardware using newer flavors without
users having to destroy and recreate their workloads.&lt;/p&gt;
&lt;p&gt;As a user, I want my servers to retain their IPs, volumes and UUID
while being migrated to another cell.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This is a complicated change, which the proof of concept patch &lt;a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; shows.
As such, I will break down this section into sub-sections to cover the various
aspects in what needs to be implemented and why.&lt;/p&gt;
&lt;p&gt;Keep in mind that at a high level, this is mostly a large data migration from
one cell to another.&lt;/p&gt;
&lt;p&gt;This spec attempts to provide a high level design based on prototypes using
both a shelve-based approach and, after initial spec review &lt;a class="footnote-reference brackets" href="#id9" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, an approach
modeled closer to the traditional resize flow. This version of the spec focuses
on the latter approach (without directly calling shelve methods). There will be
unforeseen issues that will arise during implementation so the spec tries to
not get into too low a level of implementation details and instead focuses on
the general steps needed and known issues. Open questions are called out
as necessary.&lt;/p&gt;
&lt;section id="why-resize"&gt;
&lt;h3&gt;Why resize?&lt;/h3&gt;
&lt;p&gt;We are doing resize because cells can be sharded by flavors and resize is the
only non-admin way (by default) for users to opt into migrating from one cell
with an old flavor (gen1) to a new flavor (gen2) in a new cell.&lt;/p&gt;
&lt;p&gt;Users, by naturally resizing their servers every once in a while, will help
with the migration. If not, the admins can also give them “new” flavors and
tell them they need to resize their servers by a certain date. By having this
be doable by a user-controlled process, the users can help with the migration
without knowing anything about cells underneath.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="terms"&gt;
&lt;h3&gt;Terms&lt;/h3&gt;
&lt;p&gt;Common terms used throughout the spec.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Source cell: this is the cell in which the instance “lives” when the resize
is initiated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Target cell: this is the cell in which the instance moves during a cross-cell
resize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resized instance: an instance with status &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VERIFY_RESIZE&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Super conductor: in a &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/cellsv2-layout.html#multiple-cells"&gt;split-MQ&lt;/a&gt; deployment, the super conductor is running
at the “top” and has access to the API database and thus can communicate with
the cells over RPC and directly to the cell databases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard delete: most tables in the cell database schema, like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances&lt;/span&gt;&lt;/code&gt;,
use the &lt;a class="reference external" href="https://github.com/openstack/oslo.db/blob/4.45.0/oslo_db/sqlalchemy/models.py#L142"&gt;SoftDeleteMixin&lt;/a&gt; which means when the corresponding object is
destroyed, the record’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deleted&lt;/span&gt;&lt;/code&gt; column is updated to a non-0 value which
takes it out of most queries by default, like when listing servers in the
API. This is commonly referred to as a “soft delete” of the record since it
is still in the table and will not be actually deleted until the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;archive_deleted_rows&lt;/span&gt;&lt;/code&gt; command is run. Note that this
concept of a “soft deleted” record is not the same as a server with status
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SOFT_DELETED&lt;/span&gt;&lt;/code&gt; in the API, which is a server that is marked for deletion
but has not yet been reaped by the nova-compute service. Hard deleting cell
database records is necessary in a cross-cell resize to avoid
DBDuplicateEntry failures due to unique constraint violations because of
soft deleted records in a cell database to which an instance is being
resized.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="assumptions"&gt;
&lt;h3&gt;Assumptions&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;There is a lack of connectivity, e.g. SSH access, between compute hosts in
different cells on which regular resize relies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The image service (glance), persistent volume storage (cinder) and tenant
networks (neutron) span cells.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="goals"&gt;
&lt;h3&gt;Goals&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Minimal changes to the overall resize flow as seen from both an external
(API user, notification consumer) and internal (nova developer) perspective.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain the ability to easily rollback to the source cell in case the
resize fails.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="policy-rule"&gt;
&lt;h3&gt;Policy rule&lt;/h3&gt;
&lt;p&gt;A new policy rule &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute:servers:resize:cross_cell&lt;/span&gt;&lt;/code&gt; will be added. It will
default to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;!&lt;/span&gt;&lt;/code&gt; which means no users are allowed. This is both backward
compatible and flexible so that operators can determine which users in their
cloud are allowed to perform a cross-cell resize. For example, it probably
makes sense for operators to allow only system-level admins or test engineers
to perform a cross-cell resize initially.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="resize-flow"&gt;
&lt;h3&gt;Resize flow&lt;/h3&gt;
&lt;p&gt;This describes the flow of a resize up until the point that the server
goes to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VERIFY_RESIZE&lt;/span&gt;&lt;/code&gt; status.&lt;/p&gt;
&lt;section id="api"&gt;
&lt;h4&gt;API&lt;/h4&gt;
&lt;p&gt;The API will check if the user is allowed, by the new policy rule, to perform
a cross-cell resize &lt;em&gt;and&lt;/em&gt; if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-compute&lt;/span&gt;&lt;/code&gt; service on the source host
is new enough to support the cross-cell resize flow. If so, the API will
modify the RequestSpec to tell the scheduler to not restrict hosts to the
source cell, but the source cell will be “preferred” by default.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id51"&gt;2.56 microversion&lt;/a&gt; allows users with the admin role to specify a
target host during a cold migration. Currently, the API validates that the
&lt;a class="reference external" href="https://github.com/openstack/nova/blob/c295e395d/nova/compute/api.py#L3570"&gt;target host exists&lt;/a&gt; which will only work for hosts in the same cell in
which the instance lives (because the request context is targeted to that
cell). If the request is allowed to perform a cross-cell resize then we
will adjust the target host check to allow for other cells as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="scheduler"&gt;
&lt;h4&gt;Scheduler&lt;/h4&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CrossCellWeigher&lt;/span&gt;&lt;/code&gt; will be introduced which will prefer hosts from the
source cell by default. A configurable multiplier will be added to control the
weight in case an operator wants to prefer cross cell migrations. This weigher
will be a noop for all non-cross-cell move operations.&lt;/p&gt;
&lt;p&gt;Note that once the scheduler picks a primary selected host, all alternate hosts
come from the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/c295e395d/nova/scheduler/filter_scheduler.py#L399"&gt;same cell&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="super-conductor"&gt;
&lt;h4&gt;(Super)Conductor&lt;/h4&gt;
&lt;p&gt;The role of conductor will be to synchronously orchestrate the resize between
the two cells. Given the assumption that computes in different cells do not
have SSH access to each other, the traditional resize flow of transferring
disks over SSH will not work.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationTask&lt;/span&gt;&lt;/code&gt; will check the selected destinations from the scheduler
to see if they are in another cell and if so, call off to a new set of
conductor tasks to orchestrate the cross-cell resize. Conductor will set
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.cross_cell_move=True&lt;/span&gt;&lt;/code&gt; which will be used in the API to control
confirm/revert logic.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CrossCellMigrationTask&lt;/span&gt;&lt;/code&gt; will orchestrate the following sub-tasks which
are meant to mimic the traditional resize flow and will leverage new compute
service methods.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target DB Setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before we can perform any checks in the destination host, we have to first
populate the target cell database with the instance and its related data, e.g.
block device mappings, network info cache, instance actions, etc.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;After this point, if anything fails the conductor task will hard
delete the instance and its related records from the target cell DB
so the resize can be attempted again once the issue is resolved in
the target cell.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In order to hide the target cell instance from the API when listing servers,
the instance in the target cell will be created with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden=True&lt;/span&gt;&lt;/code&gt; field
which will be used to filter out these types of instances from the API.
Remember that at this point, the instance mapping in the API points at the
source cell, so &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt; would still only show details
about the instance in the source cell. We use the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden&lt;/span&gt;&lt;/code&gt; field to
prevent leaking out the wrong instance to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;. We may also
do this for the related &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrations&lt;/span&gt;&lt;/code&gt; table record to avoid returning multiple
instances of the same migration record to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/os-migrations&lt;/span&gt;&lt;/code&gt;
(coincidentally the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrations&lt;/span&gt;&lt;/code&gt; table already has an unused &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden&lt;/span&gt;&lt;/code&gt;
column).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prep Resize at Dest&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Conductor will make a synchronous RPC call (using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;long_rpc_timeout&lt;/span&gt;&lt;/code&gt;) to a
new method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;prep_snapshot_based_resize_at_dest&lt;/span&gt;&lt;/code&gt; on the dest compute service
which will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ResourceTracker.resize_claim()&lt;/span&gt;&lt;/code&gt; on the potential dest host in the
target cell to claim resources prior to starting the resize. Note that
VCPU, MEMORY_MB and DISK_GB resources will actually be claimed (allocated)
via placement during scheduling, but we need to make the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resize_claim()&lt;/span&gt;&lt;/code&gt;
for NUMA/PCI resources which are not yet modeled in placement, and in order
to create the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationContext&lt;/span&gt;&lt;/code&gt; record.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify the selected target host to ensure ports and volumes will work.
This validation will include creating port bindings on the target host
and ensuring volume attachments can be connected to the host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If either of these steps fail, the target host will be rejected. At that point,
the conductor task will loop through alternate hosts looking for one that
works. If the migration fails at this point (runs out of hosts), then the
migration status changes to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;error&lt;/span&gt;&lt;/code&gt; and the instance status goes back to
its previous state (either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ACTIVE&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Copy the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance.migration_context&lt;/span&gt;&lt;/code&gt; from the target DB to the source DB.
This is necessary for the API to route &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;network-vif-plugged&lt;/span&gt;&lt;/code&gt; events later
when spawning the guest in the target cell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prep Resize at Source&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Conductor will make a synchronous RPC call (using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;long_rpc_timeout&lt;/span&gt;&lt;/code&gt;) to a
new method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;prep_snapshot_based_resize_at_source&lt;/span&gt;&lt;/code&gt; on the source compute
service which will behave very similar to how shelve works, but also coincides
with how the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resize_instance&lt;/span&gt;&lt;/code&gt; method works during a traditional resize:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Power off the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For non-volume-backed instances, create and upload a snapshot image of the
root disk. Like shelve, this snapshot image will be used temporarily during
the resize and upon successful completion will be deleted. The old/new
image_ref will be stored in the migration_context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Destroy the guest on the hypervisor but retain disks, i.e. call
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;self.driver.destroy(...,&lt;/span&gt; &lt;span class="pre"&gt;destroy_disks=False)&lt;/span&gt;&lt;/code&gt;. This is necessary to
disconnect volumes and unplug VIFs from the source host, and is actually
very similar to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrate_disk_and_power_off&lt;/span&gt;&lt;/code&gt; method called on the
source host during a normal resize. Note that we do not free up tracked
resources on the source host at this point nor change the instance host/node
values in the database in case we revert or need to recover from a failed
migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete old volume attachments and update the BlockDeviceMapping records
with new placeholder volume attachments which will be used on the dest host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open question: at this point we may want to activate port bindings for the
dest host, but that may not be necessary (that is not done as part of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resize_instance&lt;/span&gt;&lt;/code&gt; on the source host during traditional resize today).
If the ports are bound to the dest host and the migration fails, trying to
recover the instance in the source cell via rebuild may not work (see
&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1659062"&gt;bug 1659062&lt;/a&gt;) so maybe port binding should be delayed, or we have to be
careful about rolling those back to the source host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the migration fails at this point, any snapshot image created should be
deleted. Recovering the guest on the source host should be as simple as
hard rebooting the server (which is allowed with servers in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ERROR&lt;/span&gt;&lt;/code&gt; status).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Finish Resize at Dest&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At this point we are going to switch over to the dest host in the target cell
so we need to make sure any DB updates required from the source cell to the
target cell are made, for example, task_state, power_state, availability_zone
values, instance action events, etc&lt;/p&gt;
&lt;p&gt;Conductor will make a synchronous RPC call (using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;long_rpc_timeout&lt;/span&gt;&lt;/code&gt;) to a
new method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;finish_snapshot_based_resize_at_dest&lt;/span&gt;&lt;/code&gt; on the dest compute service
which will behave very similar to how unshelve works, but also coincides with
how the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;finish_resize&lt;/span&gt;&lt;/code&gt; method works during a traditional resize:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Apply the migration context and update the instance record for the new
flavor and host/node information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update port bindings / PCI mappings for the dest host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prepare block devices (attach volumes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spawn the guest on the hypervisor which will connect volumes and plug VIFs.
The new flavor will be used and if a snapshot image was previously created
for a non-volume-backed instance, that image will be used for the root disk.
At this point, the virt driver should wait for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;network-vif-plugged&lt;/span&gt;&lt;/code&gt;
event to be routed from the API before continuing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the temporary snapshot image (if one was created). This is similar to
how unshelve works where the shelved snapshot image is deleted. At this point
deleting the snapshot image is OK since the guest is spawned on the dest host
and in the event of a revert or recovery needed on the source, the source
disk is still on the source host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the instance as resized.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Back in conductor, we need to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mark the target cell instance record as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden=False&lt;/span&gt;&lt;/code&gt; so it will show
up when listing servers. Note that because of how the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/c295e395d/nova/compute/api.py#L2684"&gt;API filters&lt;/a&gt;
duplicate instance records, even if the user is listing servers at this exact
moment only one copy of the instance will be returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the instance mapping to point at the target cell. This is so that
the confirm/revert actions will be performed on the resized instance in the
target cell rather than the destroyed guest in the source cell.
Note that we could do this before finishing the resize on the dest host, but
it makes sense to defer this until the instance is successfully resized
in the dest host because if that fails, we want to be able to rebuild in the
source cell to recover the instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the source cell instance record as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden=True&lt;/span&gt;&lt;/code&gt; to hide it from the
user when listing servers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="confirm-flow"&gt;
&lt;h3&gt;Confirm flow&lt;/h3&gt;
&lt;p&gt;When confirming a resized server, if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.cross_cell_move&lt;/span&gt;&lt;/code&gt; value
is True, the API will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;RPC call to the source compute to cleanup disks
similar to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;driver.confirm_migration&lt;/span&gt;&lt;/code&gt; method and drop the move claim
(free up tracked resource usage for the source node).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete migration-based resource allocations against the source compute node
resource provider (this can happen in the source compute or the API).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard delete the instance and its related records from the source cell
database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.status&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;confirmed&lt;/span&gt;&lt;/code&gt; in the target cell DB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drop the migration context on the instance in the target cell DB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the instance vm_state to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ACTIVE&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt; based on its
current power_state in the target cell DB (the user may have manually powered
on the guest to verify it before confirming the resize).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revert-flow"&gt;
&lt;h3&gt;Revert flow&lt;/h3&gt;
&lt;p&gt;Similar to the confirm flow, a cross-cell revert resize will be identified
via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.cross_cell_move&lt;/span&gt;&lt;/code&gt; field in the API. If True, the API will
RPC cast to a new conductor method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;revert_cross_cell_resize&lt;/span&gt;&lt;/code&gt; which will
execute a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CrossCellRevertResizeTask&lt;/span&gt;&lt;/code&gt;. That task will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Update the instance and its related records in the source cell database
based on the contents of the target cell database. This is especially
important for things like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;BDMs because you can attach/detach volumes to/from a resized server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;REVERT_RESIZE&lt;/span&gt;&lt;/code&gt; instance action record created by the API in the
target cell. That is needed to track events during the revert in the
source cell compute.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thankfully the API does not allow attaching/detaching ports or changing
server tags on a resized server so we do not need to copy those back across
to the source cell database.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the source cell DB instance as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden=False&lt;/span&gt;&lt;/code&gt; to show it from the API
while listing servers as we revert.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the instance mapping to point at the source cell. This needs to happen
before spawning in the source cell so that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;network-vif-plugged&lt;/span&gt;&lt;/code&gt;
event from neutron is routed properly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the target cell DB instance as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden=True&lt;/span&gt;&lt;/code&gt; to hide it from the API
while listing servers as we revert.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC call the dest compute to terminate the instance (destroy the guest,
disconnect volumes and ports, free up tracked resources).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard delete the instance and its related records from the target cell
database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.status&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reverted&lt;/span&gt;&lt;/code&gt; in the source cell DB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC call the source compute to revert the migration context, apply the old
flavor and original image, attach volumes and update port bindings, power on
the guest (like in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;driver.finish_revert_migration&lt;/span&gt;&lt;/code&gt;) and swap source node
allocations held by the migration record in placement to the instance record.&lt;/p&gt;
&lt;p&gt;Note that an alternative to keeping the source disk during resize is to
use the snapshot image during revert and just spawn from that (rather than
power on from the retained disk). However, that means needing to potentially
download the snapshot image back to the source host and ensure the snapshot
image is cleaned up for both confirm and revert rather than just at the end
of the resize. It would also complicate the ability to recover the guest
on the source host by simply hard rebooting it in case the resize fails.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="limitations"&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://github.com/openstack/nova/blob/c295e395d/nova/compute/manager.py#L7082"&gt;_poll_unconfirmed_resizes&lt;/a&gt; periodic task, which can be configured to
automatically confirm pending resizes on the target host, will not support
cross-cell resizes because doing so would require an up-call to the API to
confirm the resize and cleanup the source cell database. Orchestrating
automatic cross-cell resize confirm could be a new periodic task written in
the conductor service as a future enhancement.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="known-issues"&gt;
&lt;h3&gt;Known issues&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Rather than conductor making synchronous RPC calls during the resize with
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;long_rpc_timeout&lt;/span&gt;&lt;/code&gt; configuration option, a new option could be added
specifically for cross-cell (snapshot-based) resize operations. Given a
snapshot of a large disk could take a long time to upload (or download) it
might be better to add new options for controlling those timeouts. For the
initial version of this feature we will re-use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;long_rpc_timeout&lt;/span&gt;&lt;/code&gt; and we
can add more granular options in the future if necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One semantic difference in the API will be different events under the
instance actions records during a resize, since the events are created via
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wrap_instance_event&lt;/span&gt;&lt;/code&gt; decorator on the compute methods, and when using
new methods with new names there will be new events compared to a normal
resize. This could maybe be countered by passing a specific name to
the decorator rather than just use the function name as it does today.
Given there are no API guarantees about the events that show up under an
action record, and this has always been internal details that leak out of
the API, we will not try to overwrite the new function/event names, e.g.
recording a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute_prep_resize&lt;/span&gt;&lt;/code&gt; event when calling the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;prep_snapshot_based_resize_at_dest&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol class="arabic simple" id="personality-files" start="3"&gt;
&lt;li&gt;&lt;p&gt;Servers created with personality files, commonly known as file injection,
that are resized across cells will lose the personality files since they are
not persisted in the database. There are two ways to view this. First is
that a traditional resize will preserve a config drive with the personality
files in it, so this would be a regression from that behavior since the
config drive is going to get rebuilt on the destination host during a cross
cell resize. On the other hand, servers with personality files that are
resized today but do not have a config drive already lose their personality
files during the migration because the files are not persisted and therefore
even if they get metadata in the guest from the metadata API, they will not
get the personality files used during server create (or the last rebuild).
Similarly, servers that are evacuated, even if they had a config drive, will
lose the personality files during the evacuation since the config drive is
rebuilt on the destination host. It is also worth noting that the use of
personality files &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/deprecate-file-injection.html"&gt;is deprecated&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="edge-cases"&gt;
&lt;h3&gt;Edge cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;If the user deletes a server in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VERIFY_RESIZE&lt;/span&gt;&lt;/code&gt; status, the API confirms
the resize to clean up the source host before deleting the server from the
dest host &lt;a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This code will need to take into account a cross-cell resize
and cleanup appropriately (cleanup the source host and delete records from
the source cell).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When &lt;a class="reference external" href="https://github.com/openstack/nova/blob/c295e395d/nova/compute/api.py#L4883"&gt;routing network events&lt;/a&gt; in the API, if the instance has a migration
context it will lookup the migration record based on id rather than uuid
which may be wrong if the migration context was created in a different cell
database where the id primary key on the migration record is different.
It is not clear if this will be a problem but it can be dealt with in a few
ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Store the migration.uuid on the migration context and lookup the migration
record using the uuid rather than the id.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When copying the migration context from the target cell DB to the source
cell DB, update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationContext.migration_id&lt;/span&gt;&lt;/code&gt; to match the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Migration.id&lt;/span&gt;&lt;/code&gt; of the source cell migration record.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is possible to attach/detach volumes to/from a resized server. Because of
this, mirroring those block device mapping changes from the target cell DB
to the source cell DB during revert adds complication but it is
manageable &lt;a class="footnote-reference brackets" href="#id11" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. The ability to do this to resized servers is not well
known and arguably may not be officially supported to preserve any volumes
attached during the revert, but because that is what works today we should
try and support it for cross-cell resize.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="lift-and-shift"&gt;
&lt;h4&gt;Lift and shift&lt;/h4&gt;
&lt;p&gt;Users (or cloud operators) could force existing servers to be snapshot,
destroyed and then re-created from snapshot with a new flavor in a new cell.
It is assumed that deployments already have some kind of tooling like this for
moving resources across sites or regions. While normal resize is already
disruptive to running workloads, this alternative is especially problematic if
specific volumes and ports are attached, i.e. the IP(s) and server UUID would
change. In addition, it would require all multi-cell deployments to orchestrate
their own cross-cell migration tooling.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="shelve-orchestration"&gt;
&lt;h4&gt;Shelve orchestration&lt;/h4&gt;
&lt;p&gt;An alternative design to this spec is found in the PoC &lt;a class="footnote-reference brackets" href="#id8" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and initial version
of this spec &lt;a class="footnote-reference brackets" href="#id9" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. That approach opted to try and re-use the existing
shelve and unshelve functions to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Snapshot and shelve offload out of the source cell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unshelve from snapshot in the target cell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On revert, shelve offload from the target cell and then unshelve in the
source cell.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The API, scheduler and database manipulation logic was similar &lt;em&gt;except&lt;/em&gt; since
shelve was used, the instance was offloaded from the source cell which could
complicate getting the server &lt;em&gt;back&lt;/em&gt; to the original source on revert and
require rescheduling to a different host in the source cell.&lt;/p&gt;
&lt;p&gt;In addition, that approach resulted in new task states and notifications
related to shelve which would not be found in a normal resize, which could be
confusing, and complicated the logic in the shelve/unshelve code since it had
to deal with resize conditions.&lt;/p&gt;
&lt;p&gt;Comparing what is proposed in this spec versus the shelve approach:&lt;/p&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Arguably cleaner with new methods to control task states and notificiations;
no complicated dual-purpose logic to shelve handling a resize, i.e. do not
repeat the evacuate/rebuild debt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The source instance is mostly untouched which should make revert and
recover simpler.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Lots of new code, some of which is heavily duplicated with shelve/unshelve.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Long-term it should be better to try for a hybrid approach (what is in this
spec) to have new compute methods to control notifications and task states to
closer match a traditional resize flow, but mix in shelve/unshelve style
operations, e.g. snapshot, guest destroy/spawn.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cross_cell_move&lt;/span&gt;&lt;/code&gt; boolean column, which defaults to False, will be added
to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrations&lt;/span&gt;&lt;/code&gt; cell DB table and related versioned object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden&lt;/span&gt;&lt;/code&gt; boolean column, which defaults to False, will be added to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances&lt;/span&gt;&lt;/code&gt; cell DB table and related versioned object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no explicit request/response schema changes to the REST API.
Normal resize semantics like maintaining the same task state transition and
keeping the instance either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ACTIVE&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTDOWN&lt;/span&gt;&lt;/code&gt; at the end will remain
intact.&lt;/p&gt;
&lt;p&gt;While the instance is resized and contains records in both cells, the API will
have to take care to filter out duplicate instance and migration records while
listing those across cells (using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hidden&lt;/span&gt;&lt;/code&gt; field).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;As described in the &lt;a class="reference internal" href="#policy-rule"&gt;Policy rule&lt;/a&gt; section, a new policy rule will be added
to control which users can perform a cross-cell resize.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Similar to task state transitions in the API, notifications should remain
the same as much as possible. For example, the &lt;em&gt;Prep Resize at Dest&lt;/em&gt; phase
should emit the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance.resize_prep.start/end&lt;/span&gt;&lt;/code&gt; notifications.
The &lt;em&gt;Prep Resize at Source&lt;/em&gt; phase should emit the existing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance.resize.start/end/error&lt;/span&gt;&lt;/code&gt; notifications.&lt;/p&gt;
&lt;p&gt;The bigger impact will be to deployments that have a notification queue per
cell because the notifications will stop from one cell and start in another,
or be intermixed during the resize itself (prep at dest is in target cell while
prep at source is in source cell). It is not clear what impact this could have
on notification consumers like ceilometer though.&lt;/p&gt;
&lt;p&gt;If desired, new versioned notifications (or fields to existing notifications)
could be added to denote a cross-cell resize is being performed, either as
part of this blueprint or as a future enhancement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;As mentioned above, instance action events and versioned notification behavior
may be different.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Clearly a cross-cell resize will perform less well than a normal resize
given the database coordination involved and the need to snapshot an
image-backed instance out of the source cell and download the snapshot image
in the target cell.&lt;/p&gt;
&lt;p&gt;Also, deployments which enable this feature may need to scale out their
conductor workers which will be doing a lot of the orchestration work
rather than inter-compute coordination like a normal resize. Similarly, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rpc_conn_pool_size&lt;/span&gt;&lt;/code&gt; may need to be increased because of the synchronous
RPC calls involved.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will be able to control who can perform a cross-cell resize in
their cloud and also be able to tune parameters used during the resize,
like the RPC timeout.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;can_connect_volume&lt;/span&gt;&lt;/code&gt; compute driver interface will be added with
the following signature:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;can_connect_volume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;That will be used during the validation step to ensure volumes attached to
the instance can connect to the destination host in the target cell. The code
itself will be relatively minor and just involve parts of an existing volume
attach/detach operation for the driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;There are three major upgrade considerations to support this feature.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;RPC: given the RPC interface changes to the compute and conductor services,
those services will naturally need to be upgraded before a cross-cell resize
can be performed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cinder: because of the validation relying on volume attachments, cinder
will need to be running at least Queens level code with the
&lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id41"&gt;3.44 microversion&lt;/a&gt; available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neutron: because of the validation relying on port bindings, neutron will
need to be running at least Rocky level code with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Port&lt;/span&gt; &lt;span class="pre"&gt;Bindings&lt;/span&gt; &lt;span class="pre"&gt;Extended&lt;/span&gt;&lt;/code&gt; API extension enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Matt Riedemann &amp;lt;&lt;a class="reference external" href="mailto:mriedem.os%40gmail.com"&gt;mriedem&lt;span&gt;.&lt;/span&gt;os&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt; (irc: mriedem)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mriedem&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;At a high level this is the proposed series of changes that need to be made
in order, although realistically some of the control plane changes could be
made in any order as long as the cold migrate task change comes at the end.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;DB model changes (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrations.cross_cell_move&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instances.hidden&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Various versioned objects changes for tracking a cross-cell move in
the RequestSpec, looking up a Migration by UUID, creating InstanceAction
and InstanceActionEvent records from existing data, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler changes to select destination hosts from multiple cells during
a cross-cell move and weighing them so the “source” cell is preferred by
default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Possible changes to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationContext&lt;/span&gt;&lt;/code&gt; object for new fields like
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;old_image_ref&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new_image_ref&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;old_flavor&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;new_flavor&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;old_vm_state&lt;/span&gt;&lt;/code&gt; (this will depend on implementation).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova-compute RPC interface changes for the prep/validate at dest, prep
at source, and finish resize at source operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding new conductor tasks for orchestrating a cross-cell resize including
reverting a resize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API plumbing changes to handle confirming/reverting a cross-cell resize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new policy rule and make the existing resize flow use it to tell the
scheduler whether or not target hosts can come from another cell, and if the
target host is from another cell, to run the new cross-cell resize conductor
task to orchestrate the resize rather than the traditional
compute-orchestrated flow (where the source and target nova-compute services
SSH and RPC between each other).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The existing functional tests in the PoC change should give a good idea of
the types of wrinkles that need to be tested. Several obvious tests include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Resize both image-backed and volume-backed servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure allocations in the placement service, and resource reporting from
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-hypervisors&lt;/span&gt;&lt;/code&gt; API, are accurate at all points of the resize, i.e.
while the server is in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VERIFY_RESIZE&lt;/span&gt;&lt;/code&gt; status, after it is confirmed and
reverted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure volume attachments and port bindings are managed properly, i.e. no
resources are leaked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tags, both on the server and associated with virtual devices (volumes and
ports) survive across the resize to the target cell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Volumes attached/detached to/from a server in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VERIFY_RESIZE&lt;/span&gt;&lt;/code&gt; status are
managed properly in the case of resize confirm/revert.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;During a resize, resources which span cells, like the server and its
related migration, are not listed with duplicates out of the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform a resize with at-capacity computes, meaning that when we revert
we can only fit the instance with the old flavor back onto the source host
in the source cell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure start/end events/notifications are aligned with a normal same-cell
resize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resize from both an active and stopped server and assert the original
status is retained after confirming and reverting the resize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete a resized server and assert resources and DB records are properly
cleaned up from both the source and target cell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test a failure scenario where the server is recovered via rebuild in the
source cell.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unit tests will be added for the various units of changes leading up to the
end of the series where the functional tests cover the integrated flows.
Negative/error/rollback scenarios will also be covered with unit tests and
functional tests as appropriate.&lt;/p&gt;
&lt;p&gt;Since there are no direct API changes, Tempest testing does not really fit
this change. However, something we should really have, and arguably should
have had since Pike, is a multi-cell CI job. Details on how a multi-cell CI
job can be created though is unclear given the need for it to either
integrate with legacy devstack-gate tooling or, if possible, new zuul v3
tooling.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The compute admin &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/configuration/resize.html"&gt;resize guide&lt;/a&gt; will be updated to document cross-cell
resize in detail from an operations perspective, including troubleshooting
and fault recovery details.&lt;/p&gt;
&lt;p&gt;The compute &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/configuration/"&gt;configuration guide&lt;/a&gt; will be updated for the new policy rule
and any configuration options added.&lt;/p&gt;
&lt;p&gt;The compute &lt;a class="reference external" href="https://developer.openstack.org/api-guide/compute/server_concepts.html"&gt;server concepts guide&lt;/a&gt; may also need to be updated for any
user-facing changes to note, like the state transitions of a server during
a cross-cell resize.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Proof of concept: &lt;a class="reference external" href="https://review.openstack.org/#/c/603930/"&gt;https://review.openstack.org/#/c/603930/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Shelve-based approach spec: &lt;a class="reference external" href="https://review.openstack.org/#/c/616037/1/"&gt;https://review.openstack.org/#/c/616037/1/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;API delete confirm resize: &lt;a class="reference external" href="https://github.com/openstack/nova/blob/c295e395d/nova/compute/api.py#L2069"&gt;https://github.com/openstack/nova/blob/c295e395d/nova/compute/api.py#L2069&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Mirror BDMs on revert: &lt;a class="reference external" href="https://review.openstack.org/#/c/603930/20/nova/conductor/tasks/cross_cell_migrate.py@637"&gt;https://review.openstack.org/#/c/603930/20/nova/conductor/tasks/cross_cell_migrate.py@637&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;p&gt;Stein PTG discussions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-ptg-stein-cells"&gt;https://etherpad.openstack.org/p/nova-ptg-stein-cells&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-ptg-stein"&gt;https://etherpad.openstack.org/p/nova-ptg-stein&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mailing list discussions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-August/thread.html#133693"&gt;http://lists.openstack.org/pipermail/openstack-dev/2018-August/thread.html#133693&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-operators/2018-August/thread.html#15729"&gt;http://lists.openstack.org/pipermail/openstack-operators/2018-August/thread.html#15729&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Code:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/topic:bp/cross-cell-resize+(status:open+OR+status:merged"&gt;https://review.openstack.org/#/q/topic:bp/cross-cell-resize+(status:open+OR+status:merged&lt;/a&gt;)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id12"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed and added the known issue for
&lt;a class="reference internal" href="#personality-files"&gt;&lt;span class="std std-ref"&gt;personality files&lt;/span&gt;&lt;/a&gt; and details hard
deleting the instance and its related records from a cell DB.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Support re-configure delete_on_termination in server</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/destroy-instance-with-datavolume.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/destroy-instance-with-datavolume"&gt;https://blueprints.launchpad.net/nova/+spec/destroy-instance-with-datavolume&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to allow changing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt;
attribute of a volume after an instance is booted, or set the new volume’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; during swap volume.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, nova supports configuring &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; for the root
disk and data volume (refrerence to the volume attach API &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.) when the
instance is created, but does not allow it to be updated after the instance
is created.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;In large scale environment, lots of resources can be created in system, and
sometimes some discarded instances need to cleaned up from the production
environment.&lt;/p&gt;
&lt;p&gt;As the admin that is tasked with cleaning up the production environment
may be distinct from the user that created the instances, it is desirable
to be able to alter the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; property to either
preserve important data while freeing compute resources or freeing
storage space and cleaning up sensitive data.&lt;/p&gt;
&lt;p&gt;As an admin user, I expect that I can set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt;
during swap volume.&lt;/p&gt;
&lt;p&gt;The end user expects to be able to decide the policy by which the volumes
are preserved or destoryed at any point in the vms lifecyle.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to the Servers with volume attachments model,
to support configuring whether to delete the attached volume when the
instance is destroyed. Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; property to the
request body. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volume_id&lt;/span&gt;&lt;/code&gt; parameter in the url is the volume that
will be set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Change swap volume policy’s rule name to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-volumes-attachments:swap&lt;/span&gt;&lt;/code&gt;, and make the original
policy’s rule name (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-volumes-attachments:update&lt;/span&gt;&lt;/code&gt;)
allow the update a volume atachment API.&lt;/p&gt;
&lt;p&gt;Add ‘rule:system_admin_or_owner’ policy to the update volume API.&lt;/p&gt;
&lt;p&gt;After this change, the update volume attachment API will have two policies,
one for general updates (currently only &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt;) and one
for admins which allows changing the volume id (i.e. swap volume) as well
as other attributes. In other words, the swap policy is a superset of the
update policy.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Configure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; by the volume attach API (reference
to the volume attach API &lt;a class="footnote-reference brackets" href="#id3" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.), if you want to change that value with the
data volume, you could just detach and re-attach with the new value.&lt;/p&gt;
&lt;p&gt;If you boot from volume where nova creates the root volume and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination=True&lt;/span&gt;&lt;/code&gt; when you created the server, but if you want
to preserve the root volume after the server is deleted, you can create a
snapshot of the server.&lt;/p&gt;
&lt;p&gt;Another option is add a PATCH volume attachment API, allowing a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; property in the request body to support updating
the attached volume, but that will break the nova API and introduce a new
PATCH method.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Configure &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; for the volume attached to the instance.&lt;/p&gt;
&lt;p&gt;URL: /servers/{server_id}/os-volume_attachments/{volume_id}&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request method: PUT (Update a volume attachment)&lt;/p&gt;
&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; parameter to the request body.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update a volume attachment API’s request body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a07f71dc-8151-4e7d-a0cc-cd24a3f11113"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Other than &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;volumeId&lt;/span&gt;&lt;/code&gt;, as of the new microversion only
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; may be changed from the current value. Otherwise,
that will be return 400.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Add ‘rule:system_admin_or_owner’ policy role to the
update a volume attachment API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;python-novaclient will be updated to support changing
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; flag.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;zhangbailin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;zhangbailin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new microversion which enables code that allows updating
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; during a PUT request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the original policy role name for update a volume attachment API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new policy to the update a volume attachment API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change python-novaclient to support this microversion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit tests for negative scenarios such as trying to call
update a volume attachment API to update an attached volume with an older
microversion, passing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; with an invalid value
like null, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional tests for normal scenarions, e.g. API samples.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempest testing should not be necessary since in-tree functional testing
with the CinderFixture should be sufficient for testing this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Add docs description about this microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;For the discussion of this feature at the Forum in Berlin:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/BER-bfv-improvements"&gt;https://etherpad.openstack.org/p/BER-bfv-improvements&lt;/a&gt;
BFV improvements, discussion on or around line 52.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the disscussion of this feature at the Forum in Shanghai:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-shanghai-ptg"&gt;https://etherpad.openstack.org/p/nova-shanghai-ptg&lt;/a&gt;
Discussion on or around line 252.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/train/approved/support-delete-on-termination-in-server-attach-volume.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/train/approved/support-delete-on-termination-in-server-attach-volume.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Flavor Extra Spec Validator</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/flavor-extra-spec-validators.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/flavor-extra-spec-validators"&gt;https://blueprints.launchpad.net/nova/+spec/flavor-extra-spec-validators&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduce a mechanism to describe and validate flavor extra specs.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Flavor extra specs are one of the Wild West aspects of nova. There are a number
of issues we’d like to address:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Lack of documentation for many flavor extra specs &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. While Glance has
metadefs &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, those are generally out-of-date, incomplete, and not
consumable from nova and our user-facing documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No warnings or errors if there is a typo in your extra spec, resulting in
different behavior to that expected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No defined way to do things like deprecate a flavor extra spec, resulting in
continued reinvention of the wheel.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As a deployer, I’d like to know what flavor extra specs and image metadata
properties are available and why I’d want to use them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a deployer, I’d like nova to tell me when I’ve used a flavor extra spec
that doesn’t exist or has a typo in it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a developer, I’d like an easy way to deprecate flavor extra specs, which
is something that will only become more common if we do things like model
NUMA in placement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a documentation writer, I’d like to be able to cross-reference the various
flavor extra specs and image metadata properties available.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;A flavor extra spec is a key-value pair. For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cpu_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dedicated&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Different solutions are needed to validate the &lt;em&gt;value&lt;/em&gt; part of an extra spec
compared to the &lt;em&gt;key&lt;/em&gt; part. This spec aims to tackle validation of both,
however, the following are considered out-of-scope for this change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enforcement of extra spec dependencies. For example, if extra spec A requires
extra spec B be configured first. We will document the dependency but it
won’t be enforced.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In most cases this is already handled by virt drivers, though this does
occur much later in the process that what this spec proposes.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enforcement of virt driver dependencies. Unfortunately, while flavor extra
specs should be generic, this isn’t always the case. As above, we will
document this dependency but it won’t be enforced.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This change builds upon &lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/stein/implemented/flavor-extra-spec-image-property-validation.html"&gt;Flavor extra spec image metadata validation&lt;/a&gt;,
which covers some of these issues for us.&lt;/p&gt;
&lt;section id="value-validation"&gt;
&lt;h3&gt;Value validation&lt;/h3&gt;
&lt;p&gt;Value validation is the easier of the two issues to tackle. It will resolve
issues like the following in a generic manner:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cpu_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;deddddicated&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For a generic extra spec, a definition of a validator will need to contain the
following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Name or &lt;em&gt;key&lt;/em&gt; of the extra spec, e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; for the above
example. This must be patternable to handle e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_cpus.{id}&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Description of the extra spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support status of the extra spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Valid values; whether it’s an integer, a boolean, a string matching a given
regex or pattern, an enum, or something else entirely&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Virt driver dependencies; this is only for documentation purposes and will
not be enforced&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extra spec dependencies; this is only for documentation purposes and will not
be enforced&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For any extra specs defined in in-tree code, we propose also maintaining the
definitions in-tree. To do this, we propose adding a new module,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.api.validation.extra_specs&lt;/span&gt;&lt;/code&gt;, which will contain definitions for &lt;em&gt;flavor
validators&lt;/em&gt;. These will be defined using Python objects.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;numa_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtraSpecValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'hw:numa_nodes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'The number of virtual NUMA nodes to allocate to configure the '&lt;/span&gt;
        &lt;span class="s1"&gt;'guest with. Each virtual NUMA node will be mapped to a unique '&lt;/span&gt;
        &lt;span class="s1"&gt;'host NUMA node. Only supported by the libvirt virt driver.'&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'The number of virtual NUMA nodes to allocate'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'min'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;numa_cpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtraSpecValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'hw:numa_cpu.&lt;/span&gt;&lt;span class="si"&gt;{id}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'A mapping of **guest** CPUs to the **guest** NUMA node '&lt;/span&gt;
        &lt;span class="s1"&gt;'identified by ``&lt;/span&gt;&lt;span class="si"&gt;{id}&lt;/span&gt;&lt;span class="s1"&gt;``. This can be used to provide asymmetric '&lt;/span&gt;
        &lt;span class="s1"&gt;'CPU-NUMA allocation and is necessary where the number of guest '&lt;/span&gt;
        &lt;span class="s1"&gt;'NUMA nodes is not a factor of the number of guest CPUs.'&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'The ID of the **guest** NUMA node.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'The guest CPUs, in the form of a CPU map, to allocate to the '&lt;/span&gt;
            &lt;span class="s1"&gt;'guest NUMA node identified by ``&lt;/span&gt;&lt;span class="si"&gt;{id}&lt;/span&gt;&lt;span class="s1"&gt;``.'&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'pattern'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'\^?\d+((-\d+)?(,\^?\d+(-\d+)?)?)*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In addition to the extra specs defined in-tree, it is also possible for
operators to define their own extra specs that would be used by e.g. custom
scheduler filters. For these, we propose providing an entry point through which
operators can define their own custom definitions. This entry point should
point to a list of extra spec validators. These will have lower precedence than
in-tree definitions. This is not expected to be a large burden since operators
already need to provide a package for the custom scheduler filters and
documentation will be provided to help users add these.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="na"&gt;nova.extra_spec_validators&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;custom_scheduler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;custom.scheduler.extra_spec_validators:VALIDATORS&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;VALIDATORS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtraSpecValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'foo:bar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'A custom, out-of-tree validator'&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type:'&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="s1"&gt;'Whether to allow the instance to do something'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Regardless of the source of the extra spec validator, they will be used by the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavors/{flavor_id}/os-extra_specs&lt;/span&gt;&lt;/code&gt; API. A microversion will be introduced
for this API to avoid breaking existing tools that are inadvertently setting
the wrong values.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="key-validation"&gt;
&lt;h3&gt;Key validation&lt;/h3&gt;
&lt;p&gt;We also want to be able to catch invalid extra specs themselves. It will
resolve issues like the following in a generic manner:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cpu_pollllicy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dedicated&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This involves maintaining a registry of &lt;strong&gt;all&lt;/strong&gt; valid extra specs. Given that
we’re using a regex to define extra spec names and provide custom extra spec
validators via the entry point, we expect to have enough power to achieve this.
However, there may be a scenarios where an operator wishes to disable or bypass
this validation. To this end, we will add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation&lt;/span&gt;&lt;/code&gt; query parameter
to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavors/{flavor_id}/os-extra_specs&lt;/span&gt;&lt;/code&gt; API. This will accept three
possible values:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;strict&lt;/span&gt;&lt;/code&gt; (default)&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Requests for extra specs with invalid values or extra specs that we do not
have a validator for will be rejected with a HTTP 400 response.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;permissive&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Requests for extra specs with invalid values will be rejected with a HTTP
400 response. Requests for unregistered extra specs will be logged but
permitted.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;off&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Validation is disabled. No logging will occur.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;All other values will be rejected.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-changes"&gt;
&lt;h3&gt;Other changes&lt;/h3&gt;
&lt;p&gt;We also propose adding tooling to (a) render reStructuredText documentation
from the definitions and (b) convert the definitions into Glance metadata
definition files. Both of these tools will live within the nova tree, allowing
us to remain the single source of truth for these things.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We could ignore some of the above issues and try to solve others in a
piecemeal fashion. This will likely be far more tedious and time consuming as
modifications will be needed in far more places.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could introduce a configuration option to toggle strict API validation
instead of or in addition to the API microversion. This introduces a new
example of config-driven API behavior, which is something we’re trying to
remove from nova. It is also unnecessary because the use of microversions
or the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation&lt;/span&gt;&lt;/code&gt; query parameter allows users to continue using the
older behavior when absolutely necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could initially log warnings for invalid keys and introduce the API change
in a later release. This is unnecessary because the use of microversions
or the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation&lt;/span&gt;&lt;/code&gt; query parameter allows users to continue using the
older behavior when absolutely necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could introduce a new API microversion each time a new extra spec is
introduced. This would be extremely tedious, would only be possible for
in-tree extra specs, and is on the whole rather unnecessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could not add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validate&lt;/span&gt;&lt;/code&gt; query parameter and instead insist that all
extra specs be registered. However, this validation is intended to help
operators, not hurt them, and there are reasons people might want to bypass
this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could use a YAML file to describe out-of-tree extra specs rather than
custom Python objects. However, this is prone to inadvertent tampering and
forces people to learn multiple ways of configuring things.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;We will add an API microversion to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;flavors/{flavor_id}/os-extra_specs&lt;/span&gt;&lt;/code&gt;
API to return HTTP 400 on invalid flavor extra specs. We will also add support
for a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation&lt;/span&gt;&lt;/code&gt; query parameter to partially or fully disable this
behavior, if necessary.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;End users will have better documentation for the available flavor extra specs
and image metadata properties.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators will now need to describe any custom flavor extra specs used in their
deployment using custom validators or will they will see errors when using the
new API microversion without the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation&lt;/span&gt;&lt;/code&gt; parameter.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Developers should now add new flavor extra specs to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.api.validation.extra_specs&lt;/span&gt;&lt;/code&gt; module to take advantage of the validation
available.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Operators with out-of-tree scheduler filters or virt drivers may need to add
extra spec validators to their package.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;stephenfinucane&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Produce extra spec definitions for all in-tree flavor extra specs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add entry point-based loading mechanism for custom extra specs and document
how operators can and should use this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new API microversion and code to validate user-provided flavor extra
specs and these definitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a Sphinx extension to render this spec into documentation and another
tool to convert the spec into Glance metadata definitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a tool to generate glance-metadef compatible JSON files that can be
consumed by the glance metadata definitions catalog API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;There will be better docs, through the power of Sphinx. We will need to
document how operators can develop validators for their custom extra specs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/image-guide/image-metadata.html#metadata-definition-service"&gt;https://docs.openstack.org/image-guide/image-metadata.html#metadata-definition-service&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance/blob/18.0.0/etc/metadefs/compute-libvirt.json"&gt;https://github.com/openstack/glance/blob/18.0.0/etc/metadefs/compute-libvirt.json&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed with a simpler name and signficant modifications&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>image metadata prefiltering</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/image-metadata-prefiltering.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/image-metadata-prefiltering"&gt;https://blueprints.launchpad.net/nova/+spec/image-metadata-prefiltering&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova supports specifying hypervisor-specific device model via image properties.
Today when such properties are set on an image they are not considered when
scheduling unless the operator manually configures the ImagePropertiesFilter.
If the operator does not configure the ImagePropertiesFilter and an instance
is scheduled to a host that cannot support the requested device model, a late
check in the virt driver will fail the spawn and trigger a reschedule.
If only a subset of hosts can support the requested device model this
frequently results in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NoValidHost&lt;/span&gt;&lt;/code&gt; error.&lt;/p&gt;
&lt;p&gt;This proposal suggests using standardised traits and placement to address
device model compatibility by extending existing virt drivers to declare the
device models they support as traits.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I want the flexibility to deploy a heterogeneous cloud that has
compute nodes with different device model capabilities, either temporarily
during upgrades or permanently in a multi-architecture multi-hypervisor cloud,
without requiring explicit scheduler configuration.&lt;/p&gt;
&lt;p&gt;As an operator, I would like to be able to communicate with my customers what
capabilities my cloud provides opaquely via standard traits instead of
revealing the specific versions of the software that is deployed so that they
can provide their own image that depends on those capabilities.&lt;/p&gt;
&lt;p&gt;As an end user, I want to be able to succinctly specify device models or other
hypervisor-dependent capabilities requirements for my instance without needing
to be overly verbose.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="step-1-standard-traits"&gt;
&lt;h3&gt;Step 1: Standard Traits&lt;/h3&gt;
&lt;p&gt;Well-defined &lt;a class="reference external" href="https://github.com/openstack/glance/tree/master/etc/metadefs"&gt;image metadata properties&lt;/a&gt; that have a finite set of values
which represent virtualisation capabilities will be converted to standard
traits.&lt;/p&gt;
&lt;p&gt;The current proposed set is&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"hw_vif_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Virtual Network Interface"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specifies the model of virtual network interface&lt;/span&gt;
&lt;span class="s2"&gt;         device to use. The valid options depend on the hypervisor&lt;/span&gt;
&lt;span class="s2"&gt;         configuration. libvirt driver options: KVM and QEMU:&lt;/span&gt;
&lt;span class="s2"&gt;         e1000, ne2k_pci, pcnet, rtl8139, spapr-vlan, and virtio.&lt;/span&gt;
&lt;span class="s2"&gt;         Xen: e1000, netfront, ne2k_pci, pcnet, and rtl8139."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"e1000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"e1000e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"ne2k_pci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"netfront"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"pcnet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"rtl8139"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"spapr-vlan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;"hw_video_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Video Model"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The video image driver used."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"vga"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"cirrus"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"vmvga"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"xen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"qxl"&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;"hw_disk_bus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Disk Bus"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specifies the type of disk controller to&lt;/span&gt;
&lt;span class="s2"&gt;         attach disk devices to."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"scsi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"virtio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"uml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"xen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"usb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"fdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"sata"&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus&lt;/span&gt;&lt;/code&gt; supports the same values as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_disk_bus&lt;/span&gt;&lt;/code&gt; but is not
documented. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus&lt;/span&gt;&lt;/code&gt; will also be supported by this spec.  Other image
properties that may also be worth considering are:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;"hypervisor_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hypervisor Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;"Hypervisor type required by the image."&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"baremetal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"hyperv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"kvm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"lxc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"qemu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"uml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"vmware"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"vz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"xen"&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;"vm_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VM Mode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;"The virtual machine mode.&lt;/span&gt;
&lt;span class="nt"&gt;         This represents the host/guest ABI (application binary interface)&lt;/span&gt;
&lt;span class="nt"&gt;         used for the virtual machine."&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nt"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"hvm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"xen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"uml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="s2"&gt;"exe"&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;While this spec primarily targets the device model specific image metadata
properties the same pattern could be applied to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_type&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vm_mode&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Creation of the standard traits will be tracked in a &lt;a class="reference external" href="https://storyboard.openstack.org/#!/story/2005447"&gt;placement/os-traits
StoryBoard story&lt;/a&gt;. Discussion of how these traits will be
named/namespaced will happen there rather than in this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="step-2-reporting-of-capabilities-by-virt-drivers"&gt;
&lt;h3&gt;Step 2: Reporting Of Capabilities By Virt Drivers&lt;/h3&gt;
&lt;p&gt;This spec primarily targets extending the libvirt driver; however as
these properties are also used by the vmware and fake drivers they will
also be extended.&lt;/p&gt;
&lt;p&gt;To enable this feature, the virt drivers will be extended to report traits
for each device model they are capable of emulating on the compute node
resource provider. This will be done by introspection of the libvirt version,
qemu version, and Nova config such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.virt_type&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To support upgrades without modifying existing images or flavors, the late
checks for device model support in the virt driver will not be removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="step-3-requesting-a-device-model-and-scheduling"&gt;
&lt;h3&gt;Step 3: Requesting A Device Model And Scheduling&lt;/h3&gt;
&lt;p&gt;A new scheduler prefilter will be added to automatically add the new traits
to requests. As adding new options to the device models requires a change to
Nova anyway, and these get updated infrequently, we can just have a mapping
table in a prefilter that adds additional traits to the request spec by
looking up the appropriate image metadata key and appending the traits to the
unnumbered request group. This will not require changes to images to use the
feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Operators can continue to use image property filters.&lt;/p&gt;
&lt;p&gt;If the virt drivers are modified to report traits but a prefilter
is not added, the existing ability to specify required traits in an image
would be sufficient to consume the new traits. However, that would require
the image created to first specify the device model request and then also
the required traits. E.g.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vif_model=e1000,&lt;/span&gt; &lt;span class="pre"&gt;traits:COMPUTE_NET_MODEL_E1000=required&lt;/span&gt;&lt;/code&gt;.
This will work but it’s verbose.&lt;/p&gt;
&lt;p&gt;As with other recent features, we could use the traits request as a
replacement for an image metadata property. If we chose this option we could
deprecate the image metadata data values (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_vif_model&lt;/span&gt;&lt;/code&gt;) in train
and remove them in a later release. To use the feature and request a device
model going forward a trait would be used
e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;traits:COMPUTE_NET_MODEL_E1000=required&lt;/span&gt;&lt;/code&gt;.
While this may seem nicer in some respects it is more typing than the selected
option and has the disadvantage of requiring all images to be updated to
include the traits request. As such this is discarded due to the upgrade
impact.&lt;/p&gt;
&lt;p&gt;Operators can also achieve the goals of this spec by manually creating nova
host aggregates or placement aggregates, then mapping the images to aggregates
using IsolatedHostsFilter or an aggregate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member_of&lt;/span&gt;&lt;/code&gt; placement request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A &lt;a class="reference external" href="https://storyboard.openstack.org/#!/story/2005447"&gt;new set of standard traits will be added to os-traits&lt;/a&gt;.
No other data model change should be required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This is expected to improve boot performance in a heterogeneous cloud
by reducing reschedules. By passing a more constrained request to
placement this feautre should also reduce the resulting set of
allocation_candidates that are returned.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new config option will be added to enable the image metadata prefilter.
Initially this will default to disabled but that can be changed in a future
release based on feedback on the performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;No action is required on upgrade. However just as with new deployments
if the operator wishes to enable this feature they will need to
update the nova config to enable it after upgrading.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify libvirt virt driver to report traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write prefilter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config option&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://storyboard.openstack.org/#!/story/2005447"&gt;Additions in os-traits&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This can be tested entirely in the gate.
Functional and unit tests will be added.&lt;/p&gt;
&lt;p&gt;While tempest tests could be added, since we do not have a
multinode gate job with different hypervisors tempest will
not be extended.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A release note will be added and documentation of the new config option
for the prefilter will be provided. As there is no end user impact
no user facing documentation will be required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance/tree/master/etc/metadefs"&gt;Glance Metadata Definitions Catalog namespaces&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://storyboard.openstack.org/#!/story/2005447"&gt;Additions in os-traits&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Image Pre-caching support</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/image-precache-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/image-precache-support"&gt;https://blueprints.launchpad.net/nova/+spec/image-precache-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova supports caching images on demand at the compute node level for
performance reasons, but provides no ability to schedule that activity
before a rollout or maintenance window. This long-requested feature
becomes even more important when considering Edge Computing
environments, limited bandwidth, as well as high-scale rapid
application deployment.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Several of the virt drivers in Nova support the caching of base images
for improved boot performance. The first time an instance is booted
from a given image, that base image is downloaded from glance, cached,
and either copied or CoW’d to create the actual instance root
disk. Subsequent instance boots from the same image can re-use the
cached copy of the base image instead of downloading it again from
Glance. This behavior provides the following benefits:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Decreased load on the Glance server(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decreased network utilization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decreased time-to-boot latency for the second and subsequent
instances&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The latter is particularly important for situations where new
application rollouts must be performed within a specific time window,
or where scale-up operations are expected to happen quickly in
response to changing load conditions. Specifically, it can be
important to ensure that a new image is cached on all of the relevant
compute nodes prior to the upgrade window opening, or before load
unexpectedly spikes.&lt;/p&gt;
&lt;p&gt;Further, in situations where compute nodes may be remotely located in
environments where network bandwidth is limited (such as many edge
computing environments), it may be very important to push a new base
image to those nodes during times of low utilization or a maintenance
window, such that the image download process does not consume a
massive amount of bandwidth during normal operation.&lt;/p&gt;
&lt;p&gt;Because Nova does not provide a way to seed this process from the
outside, operators are currently forced to hack around the
problem. Some of the workarounds we know are being used include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Pre-booting throwaway instances on each compute node by hand to
seed the cache before deploying the real ones&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copying the images directly into the cache directories on the
compute nodes out of band&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modifying the Nova code themselves to provide this functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using a shared storage volume for the image cache (which is known to
be broken)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using a totally different ephemeral backend, such as ceph which
side-steps the problem entirely (but requires a substantially larger
investment)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator of a cloud with remote compute nodes at the network
edge, I want to be able to pre-cache images during maintenance
windows in order to avoid the network spike involved with spinning
up a new instance and pulling the base image on demand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user of a cloud which supports an application that is
frequently re-deployed en masse, I want to be able to pre-cache new
images at computes before my rollout window to limit my application
downtime to purely the time needed to respawn or rebuild instances.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This functionality has been proposed and requested multiple times, but
failed to gain traction amongst the team for various reasons. Thus,
this spec proposes a minimally viable initial implementation which
addresses the need for pre-caching, but does not provide specific
visibility, reporting, scheduling, or other advanced features.&lt;/p&gt;
&lt;p&gt;Initially we will add a mechanism to Nova, by which a
(sufficiently-privileged) user can request that a set of images be
cached on the set of compute nodes contained within a host
aggregate. This activity will be delegated to a (super-)conductor
worker, which will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Validate the images provided (for existence and accessibility, to
avoid asking a ton of computes to do something impossible)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Look up the list of hosts in the given aggregate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collate the hosts by cell&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Iterate through those hosts making an RPC request to start the
operation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we were to fire off all those requests via RPC casts to be handled
asynchronously, we would surely DDoS the image service. Throttling
that appropriately could be done in many ways and is easily the
subject of a dedicated subsequent spec. In this initial revision, we
will introduce a configurable parallelism limit, which will cause
conductor to contact that many computes in parallel to trigger their
downloads, using the long-running RPC call functionality to wait for
completion.&lt;/p&gt;
&lt;p&gt;Images will be cached on each compute using a new method on the virt
driver which, when implemented, will re-use the image downloading
routines already employed during image boot. Images that are cached
via this mechanism will be subjected to the same expiry and purge
rules as those downloaded on demand as a result of instance
boots. Subsequent calls to cache an image that is already resident
should reset the expiry timer (if applicable) from the cache. In the
case of the existing drivers that use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;imagecache&lt;/span&gt;&lt;/code&gt; module, we
will just need to &lt;em&gt;touch&lt;/em&gt; them to update their &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mtime&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative is always to do nothing. This has been requested and
proposed many times in the past, and people are currently living
without it and/or working around the limitation on their own.&lt;/p&gt;
&lt;p&gt;Another option would be to take a similar approach, but dispense with
the incremental nature. We could implement a larger API, with task and
progress reporting, scheduling (image X should be cached for Y hours,
etc) and other features that have been part of previous requests. The
reason to not do this is to avoid the risk of never completing this
because of the multitude of rabbit holes that open up with a larger
scope. See the references section for a partial list of previous
attempts that were never completed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None in this initial iteration. In the future, it may be desirable to
track images and status per-compute, which would require some
accounting in the database.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;It may technically make more sense to put this function under the
images API in Nova. However, that is marked as deprecated
currently. Since this is primarily based on the aggregate model, this
proposes to add this as an action on an aggregate.&lt;/p&gt;
&lt;section id="os-aggregates"&gt;
&lt;h4&gt;os-aggregates&lt;/h4&gt;
&lt;p&gt;A new route under the aggregate for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt; will be added for cache
management.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/os-aggregates/{aggregate_id}/images&lt;/span&gt;&lt;/code&gt; (returns 202 on success)&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f803"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4d8c3732-a248-40ed-bebc-539a6ffd25c0"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because we are attempting to provide a minimally-viable initial
implementation, the structure of the request is defined so that it
will be possible to add additional information in future
versions. This may include additional per-image information (such as
priority, TTL, etc) or information per-request, such as parallelism,
download rate, etc.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Obviously allowing any user to initiate a wide-scale moving of data
brings some inherent risk. As this proposes to be aggregate-based, the
user would likely need to already have at least the ability to list
host aggregates in order to provide one to the caching API. A policy
knob defining which users have that ability would default to the
existing ones with ability to manage host aggregates.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Without any API-based reporting of progress per-compute, emitting
notifications about the start and completion of image downloads could
be helpful. This would allow operators to monitor the process.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The clients will obviously need to gain the ability to hit this
API. Regular users should be entirely unaffected, other than
potentially noticing improved boot performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The primary goal of this change is to improve performance of instance
boots after the images are pre-cached. Certainly during the
pre-caching operation, there will be some additional load on the image
service, conductor workers coordinating the task, as well as the
computes doing the work. The actual image download operation on the
computes will use the same code paths that are currently used during
image boot.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers will need to determine which users should be allowed to
access this caching API, if any, and modify the policy accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;This will require a new RPC method on the conductor, compute, and a
corresponding call to the virt driver. Currently, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hyperv&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vmwareapi&lt;/span&gt;&lt;/code&gt; drivers use the imagecache. Initial
support will be provided for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt&lt;/span&gt;&lt;/code&gt; driver, but should be
relatively easy for the other two given they re-use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;imagecache&lt;/span&gt;&lt;/code&gt;
module.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As this initial revision of the function is best-effort, with no real
reporting or guarantees that the images are cached and by any
deadline, the upgrade impact is minimal. If the compute RPC API is
pinned to a version lower than required to make this call, then no
computes will be contacted to pre-cache the images.&lt;/p&gt;
&lt;p&gt;If the caching call is made against computes running virt drivers that
are not yet (or ever) able to participate, a warning log message will
be emitted by the base virt driver.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend the base virt driver to contain a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cache_image()&lt;/span&gt;&lt;/code&gt; method
which takes an image id. Default behavior is a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NotImplemented&lt;/span&gt;&lt;/code&gt;
exception.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cache_image()&lt;/span&gt;&lt;/code&gt; method in the libvirt driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new RPC call to the compute manager which delegates to the
virt driver. If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NotImplemented&lt;/span&gt;&lt;/code&gt; is raised, a warning message is
logged about the lack of support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new RPC call to the conductor manager to look up, collate
per cell, and call to the relevant computes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new REST API call allowing the user to make this request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a client implementation for making this call.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Patches against openstackclient, novaclient, and nova will be inter-dependent.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;As this initial phase of implementation provides no externally-visible
changes to a running deployment, testing with tempest would have to
rely on something obscure like time-to-boot latency to determine
success. Thus, functional tests will be added to ensure that the image
cache is populated by the new call, and that subsequent instance boots
do not contact the image service to perform the download.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This feature needs documentation for the operators in the admin guide,
and of course api-ref changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Proposal from 2011 where image caching was initially added, showing that pre-cache was an intended improvement after the initial implementation: &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Nova-image-cache-management"&gt;https://wiki.openstack.org/wiki/Nova-image-cache-management&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2013 proposing an alternate way to boot images to initial cache-seeding download: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/effective-template-base-image-preparing"&gt;https://blueprints.launchpad.net/nova/+spec/effective-template-base-image-preparing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2013 proposing more configurable image cache implementations, offering at least the ability to pin images on computes: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/multiple-image-cache-handlers"&gt;https://blueprints.launchpad.net/nova/+spec/multiple-image-cache-handlers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2014 proposing an entire new nova service for pre-caching images: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/image-precacher"&gt;https://blueprints.launchpad.net/nova/+spec/image-precacher&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2014 proposing a P2P-style sharing of image cache repositories between computes (amongst other things): &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/thunderboost"&gt;https://blueprints.launchpad.net/nova/+spec/thunderboost&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2014 proposing multiple mechanisms (including P2P) for pre-caching images on computes: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/compute-image-precache"&gt;https://blueprints.launchpad.net/nova/+spec/compute-image-precache&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2014 proposing a VMware-specific way to avoid the initial cache-seeding download from glance: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/datastore-image-cache-update-improvements"&gt;https://blueprints.launchpad.net/nova/+spec/datastore-image-cache-update-improvements&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2014 proposing adding xenapi driver image caching as a step towards pre-caching: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/xenapi-image-cache-management"&gt;https://blueprints.launchpad.net/nova/+spec/xenapi-image-cache-management&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2015 proposing a weigher to prefer computes with a specific image already cached: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/node-cached-image-weigher"&gt;https://blueprints.launchpad.net/nova/+spec/node-cached-image-weigher&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blueprint from 2015 proposing a pre-caching mechanism: &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/proactive-nova-image-caching"&gt;https://blueprints.launchpad.net/nova/+spec/proactive-nova-image-caching&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mailing list thread from 2015 starting with a request, and containing a response about some of the discussion we have had in the past about such a thing: &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2015-August/072457.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2015-August/072457.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Presentation from 2018 by Workday in Berlin about their local modifications (against Mitaka) to do image pre-caching: &lt;a class="reference external" href="https://youtu.be/hx_MdGI7fcc?t=947"&gt;https://youtu.be/hx_MdGI7fcc?t=947&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bug from 2018 where someone is trying to work around the lack of pre-caching with shared cache on NFS: &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1804262"&gt;https://bugs.launchpad.net/nova/+bug/1804262&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Non-Admin user can filter their instances by more filters</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/non-admin-filter-instance-by-az.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/non-admin-filter-instance-by-az"&gt;https://blueprints.launchpad.net/nova/+spec/non-admin-filter-instance-by-az&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Many instances filter are restricted to admin-only users, while the related
attribute are readable when showing instance detail for non admin users.&lt;/p&gt;
&lt;p&gt;In order to stay coherent, all existing instance filters that are related to a
field readable by default to non admin users when showing instance details,
should be allowed by default without policy modification.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The following instance filters are restricted to admin-only users (they are
ignored if provided by non admin), but the related attribute in server payload
are by default visible when displaying server informations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;config_drive&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_name&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;created_at&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;launched_at&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;terminated_at&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power_state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;task_state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vm_state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;progress&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This list was made by listing all existing admin-only instance filters &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;,
extracting those where the related attribute is readable by default for
non-admin users in the nova server show API &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This spec target only existing filters for nova list API and does not aim to
add new one.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;It can be disturbing for a regular user who make some automation againt nova
API not to be able to filter its instances againt field he can consult without
any policy modification from operators, especially if the filter exist but is
qualified as admin-only.&lt;/p&gt;
&lt;p&gt;By example, in a multiple availability zone deployment, it is a commonly
shared cloud pattern that users create their resources in multiple AZs in
order to get resilient in case of failure of one AZ.&lt;/p&gt;
&lt;p&gt;Dealing with multiple availability zone can lead to complexity for the user,
by example in case of cinder usage, you can disable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cross_az_attach&lt;/span&gt;&lt;/code&gt;
option to restrict volume attachment to be same AZ as the instance. In that
configuration, it can be really useful to the customer to be able to filter
their instance by AZ, by example in a user interface use-case, to display only
instance who can be attached to a given volume.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to servers list APIs to enable these filters
for non admin users.&lt;/p&gt;
&lt;p&gt;As non admin filters are listed in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_server_search_options&lt;/span&gt;&lt;/code&gt; function
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova/api/openstack/compute/servers.py&lt;/span&gt;&lt;/code&gt;, it will only require to add
previously described values in that list for the given microversion.&lt;/p&gt;
&lt;p&gt;Microversion bump is required in this context because API consumers need to
be able to discover whether they should expect this filter to work or not.
The mechanism for discovering that is by seeing whether a particular
microversion is supported, especially in this case where prior to this fix,
we’ll silently ignore these filters and the consumer would have no good way
of knowing whether it worked or not. Hence why it is a blueprint and not a
bugfix.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Currently the only way to allow non admin users to use these filters
is to edit the nova policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:servers:allow_all_filters&lt;/span&gt;&lt;/code&gt;,
which can be really painful to maintain during upgrades and can cause security
issue as you don’t want regular user to use filters like the hypervisor or node
one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new microversion will be added as we change the behaviour of the API for
non admin users, even if we don’t add or remove any parameter.&lt;/p&gt;
&lt;p&gt;List API will no longer ignore query string parameter for the following filters
for regular user:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;availability_zone&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;config_drive&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;key_name&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;created_at&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;launched_at&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;terminated_at&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power_state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;task_state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vm_state&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;progress&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /servers?availability_zone=az2
GET /servers/detail?availability_zone=az1
GET /servers/detail?key_name=my_key&amp;amp;config_drive=True
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Python client may add help to inform users this new filter.
Add support for the these filters in python-novaclient for the ‘nova list’
command.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Victor Coutellier&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Balazs Gibizer
Ghanshyam Mann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add filters to the non-admin whitelisted instance filters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for these filters to the ‘nova list’ operation in novaclient&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unittest&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The nova API documentation will need to be updated to reflect the
REST API changes, and adding microversion instructions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;All admin only server filters &lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=list-servers-detail#list-servers"&gt;https://docs.openstack.org/api-ref/compute/?expanded=list-servers-detail#list-servers&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Server attributes returned to non-admin &lt;a class="reference external" href="https://docs.openstack.org/api-ref/compute/?expanded=show-server-details-detail#show-server-details"&gt;https://docs.openstack.org/api-ref/compute/?expanded=show-server-details-detail#show-server-details&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Policy Default Refresh</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/policy-defaults-refresh.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/policy-defaults-refresh"&gt;https://blueprints.launchpad.net/nova/+spec/policy-defaults-refresh&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ideally most operators should be able to run without modifying policy, as
such we need to have richer defaults.&lt;/p&gt;
&lt;p&gt;When modifying policy, the defaults in policy should be easy to understand
and allow operators to easily create additional custom roles.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The default policy is not good enough, and hard to understand.&lt;/p&gt;
&lt;p&gt;Most APIs default to use one these two policy rules:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;admin_only&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;admin_or_owner&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Firstly “admin_only” is used for the global admin that is able to make almost
any change to Nova, and see all details of the Nova system.
The rule actually passes for any user with an admin role, it doesn’t matter
which project is used, any user with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; role gets this global
access.&lt;/p&gt;
&lt;p&gt;Secondly “admin_or_owner” sounds like it checks if the user is a member of a
project. However, for most APIs we use the default target which means this
rule will pass for any authenticated user. The database layer has a check
for the project id (with project_only kwargs) that ensures only users in the
correct project can access instances in that project. For example, this
database check means it is impossible to have a custom role that allows a
user to perform live-migration of a server in a different project to their
token, without the user being given the global admin role. In addition,
should a user have any role in a project, using the default policy, that user
is able to access Nova and start instances in that project (subject to any
quota limits on that project).&lt;/p&gt;
&lt;p&gt;Thirdly if you want a “reader” role, several APIs share a single policy rule
for read and write actions, i.e. we don’t have the granularity for such a role
to be added.&lt;/p&gt;
&lt;p&gt;Keystone comes with member, admin and reader roles by default. We should
use these default roles:
&lt;a class="reference external" href="https://specs.openstack.org/openstack/keystone-specs/specs/keystone/rocky/define-default-roles.html"&gt;https://specs.openstack.org/openstack/keystone-specs/specs/keystone/rocky/define-default-roles.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition, we can use the new “system scope” concept to define
which users are global administrators:
&lt;a class="reference external" href="https://specs.openstack.org/openstack/keystone-specs/specs/keystone/queens/system-scope.html"&gt;https://specs.openstack.org/openstack/keystone-specs/specs/keystone/queens/system-scope.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The following user roles should be supported by the default configuration:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;System Scoped Administrator (live-migrate, disable services, etc)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Scoped Member (create servers, delete servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;System Scoped Reader (list hosts, list all servers)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Scoped Reader (list servers)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In introducing the above new default permissions, we must ensure:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Operators using default policy are given at least one cycle to add
additional roles to users (likely via implied roles)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operators with over-ridden policy are given at least one cycle to
understand how the new defaults may or may not help them&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We will support the four new roles described in the use cases section
above.&lt;/p&gt;
&lt;p&gt;The change will be made in the following stages:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add tests to each API endpoint. Unit and Functional test of each APIs
behavior before any changes are made.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure all context.can calls specify a target, then make target a required
parameter and remove the default target. For example project_id.
Currently we use context.project_id in many place which needs to be
replaced with actual target project_id. For example, for a server action,
we need to use the project_id of the server, not the project_id of the
context which made the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change DB check from “role:admin” to “scope:system” if enforce_scope is
True. We can set system_scope on context for DB check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refresh each API endpoint picking from: SYSTEM_ADMIN, SYSTEM_READER,
PROJECT_MEMBER_OR_SYSTEM_ADMIN, PROJECT_READER_OR_SYSTEM_READER
(and a few other ones for things like keypairs), adding extra
granularity if needed. Maintain the old check_str working for
existing users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a future release, enforce_scope will be enforced to be True. The
legacy admin_or_owner style checking will be removed. At this point,
operators will have been given time to ensure all their users work
with the new policy defaults, and we will be happy we have enough
testing in place to not regress the checks we have in policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="scope"&gt;
&lt;h3&gt;Scope&lt;/h3&gt;
&lt;p&gt;Each policy rules will be covered with appropriate oslo.policy’s “scope_types”,
‘system’ and ‘project’ in nova case.&lt;/p&gt;
&lt;p&gt;For example GET /os-services will be scoped as ‘system’ so that only users
with system-scoped tokens will be authorized to access this API.&lt;/p&gt;
&lt;p&gt;POST ‘/servers/{server_id}/action (lock) will be scoped as
[‘system’, ‘project’] which means system scope token as well as project
scope token can lock the servers.&lt;/p&gt;
&lt;p&gt;PoC: &lt;a class="reference external" href="https://review.openstack.org/#/c/645452/"&gt;https://review.openstack.org/#/c/645452/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We need to allow for operators to migrate off of the old policy enforcement
system in a somewhat graceful way. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enforce_scope&lt;/span&gt;&lt;/code&gt; config option helps
us with that by giving operators a toggle to enforce scope checking when
they’re ready and they’ve audited their users and assignments.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enforce_scope&lt;/span&gt;&lt;/code&gt; config option default value is False which means if
token scope does not matches, only a warning is logged. This feature can
be enabled via config option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt; &lt;span class="pre"&gt;[oslo_policy]&lt;/span&gt; &lt;span class="pre"&gt;enforce_scope=True&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Note: the Nova use of user_id and project_id are orthogonal, when checking the
user_id we have no concept of project, and when checking project_id we care
little about the user_id.&lt;/p&gt;
&lt;p&gt;Keystone already support implied roles means assignment of one role implies
the assignment of another. New defaults roles &lt;cite&gt;reader&lt;/cite&gt;, &lt;cite&gt;member&lt;/cite&gt; also has
been added in bootstrap. If the bootstrap process is re-run, and a
&lt;cite&gt;reader&lt;/cite&gt;, &lt;cite&gt;member&lt;/cite&gt;, or &lt;cite&gt;admin&lt;/cite&gt; role already exists, a role implication
chain will be created: &lt;cite&gt;admin&lt;/cite&gt; implies &lt;cite&gt;member&lt;/cite&gt; implies &lt;cite&gt;reader&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;It means if we make something like SYSTEM_READER_OR_PROJECT_READER it implies
the PROJECT_MEMBER and SYSTEM_ADMIN also get access.&lt;/p&gt;
&lt;p&gt;New Roles and check_str:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;SYSTEM_ADMIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'rule:admin_api and system_scope:all'&lt;/span&gt;
&lt;span class="n"&gt;SYSTEM_READER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'role:reader and system_scope:all'&lt;/span&gt;
&lt;span class="n"&gt;PROJECT_MEMBER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'role:member and project_id:&lt;/span&gt;&lt;span class="si"&gt;%(project_id)s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;PROJECT_READER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'role:reader and project_id:&lt;/span&gt;&lt;span class="si"&gt;%(project_id)s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;PROJECT_MEMBER_OR_SYSTEM_ADMIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PROJECT_MEMBER&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'or'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;SYSTEM_ADMIN&lt;/span&gt;
&lt;span class="n"&gt;PROJECT_READER_OR_SYSTEM_READER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PROJECT_READER&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'or'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;SYSTEM_READER&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Below is the mapping of new roles and scope_types with legacy roles:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;Legacy&lt;/span&gt; &lt;span class="n"&gt;Rule&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;New&lt;/span&gt; &lt;span class="n"&gt;Rules&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Operation&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;scope_type&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;-------------------+----------------------------------+-----------+-----------&lt;/span&gt;
                   &lt;span class="o"&gt;|-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SYSTEM_ADMIN&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Global&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;RULE_ADMIN_API&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="n"&gt;Write&lt;/span&gt;
                   &lt;span class="o"&gt;|-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SYSTEM_READER&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Global&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="o"&gt;|&lt;/span&gt;                                  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Read&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;

                   &lt;span class="o"&gt;|-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PROJECT_MEMBER_OR_SYSTEM_ADMIN&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;RULE_ADMIN_OR_OWNER&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;                                  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Write&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="o"&gt;|-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PROJECT_READER_OR_SYSTEM_READER&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Project&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Read&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;PoC: &lt;a class="reference external" href="https://review.opendev.org/#/c/645452"&gt;https://review.opendev.org/#/c/645452&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="role"&gt;
&lt;h3&gt;Role&lt;/h3&gt;
&lt;p&gt;Once the scope has checked, we need to ensure what role the user has for their
given scope, and if that matches what the operator has allowed.&lt;/p&gt;
&lt;p&gt;We should move the following reader, member, admin pattern:&lt;/p&gt;
&lt;p&gt;The reader role is the least privileged, can generally only do non-destructive
GET API calls.&lt;/p&gt;
&lt;p&gt;The member role maps to the current default level of privilege.&lt;/p&gt;
&lt;p&gt;The admin role maps to the current admin role. Note this means live-migration
is project scoped and admin. Although if you specify a host, you would need
to have system scope to use that parameter.&lt;/p&gt;
&lt;p&gt;It is important to consider the scope_type of the policy when defining the
appropriate default roles.&lt;/p&gt;
&lt;p&gt;Because config option [oslo_policy].enforce_scope is false by default which
means scope_type is not enabled by default so it might be security leak if new
given roles can access the API out of their scope.
For example: GET /os-services will be given as ‘reader’ role and
scope_type=[‘system’] so check_str will be kept as ‘role:reader and
system_scope:all’ where system_scope:all is special check so that token of
reader role and project scope cannot access this API. Once nova default the
[oslo_policy].enforce_scope to True then, system_scope:all can be removed
from check_str (this only applies to APIs that include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;system&lt;/span&gt;&lt;/code&gt; as
one of the scope_type).&lt;/p&gt;
&lt;p&gt;PoC: &lt;a class="reference external" href="https://review.openstack.org/#/c/648480/"&gt;https://review.openstack.org/#/c/648480/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Until removed the DB level check for the admin role will be loosened also
allow access for any system scoped token.&lt;/p&gt;
&lt;p&gt;NOTE: At the same time, we will update all policy checks to specify the
correct target’s project_id. When there is no relevant project, we do not
specify a project_id at all (i.e. stop defaulting to
target={context.project_id}&lt;/p&gt;
&lt;/section&gt;
&lt;section id="granular"&gt;
&lt;h3&gt;Granular&lt;/h3&gt;
&lt;p&gt;To implement the reader role, some of the APIs do not have a granular enough
policy. We will add additional policy checks for these APIs:&lt;/p&gt;
&lt;p&gt;We will deprecate the old rule and add new granular rules.
For exmaple: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-agents&lt;/span&gt;&lt;/code&gt; will be deprecated and
new rules will be added &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-agents:delete&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-agents:get&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-agents:create&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:os-agents:update&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-agents’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/agents.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST /os-agents,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /os-agents,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-agents,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DELETE /os-agents&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-attach-interfaces’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/attach_interfaces.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/{server_id}/os-interface’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/{server_id}/os-interface/{port_id}’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/os-interface’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DELETE ‘/servers/{server_id}/os-interface/{port_id}’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-deferred-delete’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/deferred_delete.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (restore),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (forceDelete)’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-hypervisors’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/hypervisors.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors/details’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors/statistics’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors/{hypervisor_id}’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors/{hypervisor_id}/uptime’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors/{hypervisor_hostname_pattern}/search’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-hypervisors/{hypervisor_hostname_pattern}/servers’,&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-instance-actions’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/instance_actions.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/{server_id}/os-instance-actions’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/{server_id}/os-instance-actions/{request_id}’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-instance-usage-audit-log’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/instance_usage_audit_log.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-instance_usage_audit_log’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-instance_usage_audit_log/{before_timestamp}’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-remote-consoles’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/remote_consoles.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (os-getRDPConsole)’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (os-getSerialConsole)’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (os-getSPICEConsole)’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (os-getVNCConsole)’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/remote-consoles’,&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-rescue’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/rescue.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (rescue)’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (rescue)’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-security-groups’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/security_groups.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (addSecurityGroup)’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/action (removeSecurityGroup)’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-server-password’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/server_password.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/{server_id}/os-server-password’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DELETE ‘/servers/{server_id}/os-server-password’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:servers:show:host_status:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/servers.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/{server_id}’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/servers/detail’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘network:attach_external_network’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/ servers.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST  ‘/servers’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST ‘/servers/{server_id}/os-interface’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-services’:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;File: nova/policies/ services.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;APIs Operation it control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PUT  ‘/os-services/enable’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT ‘/os-services/disable’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET ‘/os-services’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT ‘/os-services/disable-log-reason’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT ‘/os-services/force-down’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT ‘/os-services/{service_id}’,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT ‘/os-services/{service_id}’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below policies have same issue but their APIs are deprecated so this proposal
would not change anything in these.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-floating-ips-bulk’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-fping’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-hosts’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-networks’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-networks-associate’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-security-group-default-rules’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-baremetal-nodes’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-fixed-ips’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-floating-ip-dns’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-floating-ips’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-multinic’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-tenant-networks’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_compute_api:os-volumes’&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PoC: &lt;a class="reference external" href="https://review.openstack.org/#/c/645427/"&gt;https://review.openstack.org/#/c/645427/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="backward-compatibility-and-migration-plan"&gt;
&lt;h3&gt;Backward Compatibility and Migration plan&lt;/h3&gt;
&lt;p&gt;Old rules are maintained as deprecated rule with same defaults as today
so that existing deployement will keep working as it is.&lt;/p&gt;
&lt;p&gt;For two cycle (this is big updates so I think we should give two cycle
transition period to operators), we need existing user permissions to
work alongside the new set of roles, so operators can migrate their
users to the new roles.&lt;/p&gt;
&lt;p&gt;Note this means:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove any project or user checks from the policy file defaults, as this
is now done in code, without breaking user-id-based-policy-enforcement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Things the reader is not allowed access in the future, but currently anyone
with a role can access must get an explicit not reader role check&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;System scope check failures only log a warning for this cycle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;etc…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will be done by using the oslo.policy’s deprecation methods. That way
we can allow the access with old check_str as well with new check_str with
appropriate warnings.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deprecation Plan:
Because these policy updates are huge and almost effecting all the nova
policies, We are defining the two cycle transition plan which used to be
one cycle for policy and config option modification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Below warning can be seen by operator to migrate the old policies
to new one:&lt;/p&gt;
&lt;p&gt;/opt/stack/nova/.tox/py27/local/lib/python2.7/site-packages/oslo_policy/
policy.py:665: UserWarning: Policy “os_compute_api:os-services”:
“rule:admin_api” was deprecated in 19.0.0 in favor of “compute:services:
disable”:”rule:admin_api”. Reason:
Since Stein release, nova API policies are more granular and introducing
new default roles with scope_type capabilities. These new changes improve
the security level, manageability. New policies are more rich in term of
handling access at system and project level with read, write roles. Nova
APIs are consuming these new policies improvements and automatically
migrate the old overridden policies. Old policies are silently going to
be ignored in nova 21.0.0 (OpenStack U) release.
. Either ensure your deployment is ready for the new default or
copy/paste the deprecated policy into your policy file and maintain it
manually.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example: &lt;a class="reference external" href="https://review.opendev.org/#/c/662971/"&gt;https://review.opendev.org/#/c/662971/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could do only one or two of the above steps, but seems more efficient
to fix these issues in one go.&lt;/p&gt;
&lt;p&gt;Instead of deprecated rule, we can have a fallback mechanish of registering
the either the new or old policy defaults in the base based on
CONF.oslo_policy.enforce_scope.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;Existing users should be unaffected by these changes till the deprecated
policies are removed or enforce_scope is enabled.&lt;/p&gt;
&lt;p&gt;Once enforcing scope, system scope users will need to learn how to request
system scoped tokens. But regular project scoped tokens remain the same for
the majority of users.&lt;/p&gt;
&lt;p&gt;Operators should be able to create new roles with more restrictive permissions
in the near future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Easier to understand policy defaults will help keep the system secure.&lt;/p&gt;
&lt;p&gt;Once the deprecated defaults are dropped, we will be able to have users with
a role in a project and not have any access to Nova (i.e. a swift only user).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;New APIs must add policies that follow the new pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The API policies name and defaults roles has been modified which
might effect the deployment if it use the default policy defined
in nova. If deployment overrides these policies then, they need to
start considering the new default policy rules.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johnthetubaguy
melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Improve policy rule unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add policy functional tests for current behavior&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for system scoped admin and project scoped member&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Loose the DB check for system scoped users, update functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add System Reader and Project Reader, add additional policy rules
where extra granularity is needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The current unit tests are generally quite bad at testing policy, this should
be addressed before making any of the above changes.&lt;/p&gt;
&lt;p&gt;Modify the Tempest tests for scope and default roles.&lt;/p&gt;
&lt;p&gt;Focus on functional tests to cover the DB check and policy do the right thing
today, so we know as the code evolves we don’t break existing users.&lt;/p&gt;
&lt;p&gt;Patrole may be considered later, as it would be useful for operators to
validate their cloud’s policy works the way they intended.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;API Reference should be kept consistent with any policy changes, in particular
around the default reader role.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Server move operations with ports having resource request</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/support-move-ops-with-qos-ports-ussuri.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-move-ops-with-qos-ports-ussuri"&gt;https://blueprints.launchpad.net/nova/+spec/support-move-ops-with-qos-ports-ussuri&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Since &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-stein"&gt;microversion 2.72&lt;/a&gt; nova supports creating servers with neutron ports
having resource request. Since the Train release nova also supports cold
migrating and resizing such servers. However other move operations i.e. live
migration, evacuation and unshelve after shelve offload are still not
possible due to missing resource handling implementation in nova.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The admin needs to be able to request the same life-cycle operations
for these servers as for any other servers.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To support live-migrate, evacuate and unshelve we will follow the
implementation pattern that is described in the &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/train/approved/support-move-ops-with-qos-ports.html"&gt;Train spec&lt;/a&gt; and then
implemented for cold migrate and resize during the Train release.&lt;/p&gt;
&lt;p&gt;During the Train implementation the &lt;a class="reference external" href="https://github.com/openstack/nova/blob/4d034b79eb4483848fa8346149d0387af4eeaa2a/nova/compute/rpcapi.py#L367"&gt;compute RPC API&lt;/a&gt; methods were extended
with the necessary RequestSpec parameter for every move operation. So no
further RPC change is expected during the implementation of this spec.&lt;/p&gt;
&lt;p&gt;During evacuate and unshelve operations the compute manager is responsible to
update the port binding in neutron. These code paths will be extended to also
update the allocation key in the port binding according to the allocation on
the target host.&lt;/p&gt;
&lt;p&gt;During live-migrate nova uses the multiple bindings API of neutron to manage
the bindings on the source and the target host in parallel. The conductor
creates the new, inactive binding on the destination host in neutron and it
will add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation&lt;/span&gt;&lt;/code&gt; key in the new binding according to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt;. When the live-migrate finishes the source port binding is
deleted along with the source host allocation. If the live-migration is
rolled back the source host binding still has the proper &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocation&lt;/span&gt;&lt;/code&gt; key
set.&lt;/p&gt;
&lt;p&gt;From the not-yet-supported move operations only live-migration has a reschedule
loop. It is handled in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LiveMigrationTask&lt;/span&gt;&lt;/code&gt; in the super conductor.
During reschedule the allocation key of the port binding of the neutron ports
needs to be updated according to the new allocation on the newly selected
target host.&lt;/p&gt;
&lt;p&gt;The multiple bindings neutron API extension cannot be turned off so if it is
not present nova can fail the live-migrate operation if ports have resource
request.&lt;/p&gt;
&lt;p&gt;Currently these move operations are rejected by nova if the server has ports
attached with resource request. After the above proposed change is implemented
these operations will be allowed. The way we will signal that nova is capable
of supporting these operations is described in the &lt;a class="reference internal" href="#rest-api-impact"&gt;REST API impact&lt;/a&gt; section.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;At the Train PTG we &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005807.html"&gt;agreed&lt;/a&gt; to implement the support for the move operations
as bugfixes without any new microversion. After the implementation is done the
code that currently rejects the move operations are removed from the API and
nova will accept and support these operations with any microversion.&lt;/p&gt;
&lt;p&gt;This is what we did with cold migrate and resize in Train and will follow that
pattern in Ussuri.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;During move operations the conductor needs to query neutron to get the
resource request of the ports that are attached to the server. Also, after the
scheduling the request group - resource provider mapping needs to be
recalculated and the binding:profile of the ports needs to be updated in
neutron.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As the solution depends on a minimum RPC version and as it requires compute
manager changes the move operations can only be supported after both the
source and the destination host are upgraded. So the conductor needs to ensure
that the service version of both computes is high enough. However if the
conductor is configured with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[upgrade_levels]compute=auto&lt;/span&gt;&lt;/code&gt;
(e.g. rolling upgrade) or the compute RPC is manually pinned then even if both
the source and the destination computes are new enough the destination compute
may still not get the necessary information to perform the port binding update.
Therefore an additional check is needed based on the actual RPC version used
towards the destination compute. These checks will be similar to the ones that
were implemented for &lt;a class="reference external" href="https://github.com/openstack/nova/blob/4d034b79eb4483848fa8346149d0387af4eeaa2a/nova/conductor/tasks/migrate.py#L383"&gt;cold migration&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The support for move operations makes it possible to heal missing or
inconsistent port allocations as during the move the requested resources are
re-calculated and the new allocation created accordingly in placement. This
will complement &lt;a class="reference external" href="https://review.openstack.org/#/c/637955"&gt;the port allocation healing capabilities&lt;/a&gt; of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;placement&lt;/span&gt; &lt;span class="pre"&gt;heal_allocations&lt;/span&gt;&lt;/code&gt; CLI that has multiple limitations in
this regard.&lt;/p&gt;
&lt;p&gt;In general the operators having incomplete port allocations are recommended to
try to heal that with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;heal_allocations&lt;/span&gt;&lt;/code&gt; CLI in place if possible to
minimize the number for server move operations required.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mriedem&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;For each move operation:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Before scheduling, gather the requested resource from neutron and update
the RequestSpec accordingly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After the scheduler selected the destination of the move operation calculate
the resource provider - request group mapping and update the neutron port
binding according to the destination allocation. This happens on the compute
side for evacuate and unshelve but happens still in the conductor for live
migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are SRIOV interfaces involved update the InstancePciRequest to drive
the PCI resource claim on the destination compute to consume VFs from the
same PF as the port resources are allocated from.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For live migration the reschedule also needs to be handled in the super
conductor.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Each move operation will have a functional test asserting that the proper
allocation exists after the move, old allocations are removed, and the port
binding in neutron refers to the appropriate resource provider.&lt;/p&gt;
&lt;p&gt;For live migration reschedule also needs to be covered with functional tests.&lt;/p&gt;
&lt;p&gt;When the source compute is recovered the compute manager cleans up the
evacuated instances. We need test coverage to make sure that the bandwidth
allocation is cleaned up from the source host but the neutron port binding is
not changed as it is expected to already point to the target host allocation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API guide &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/port_with_resource_request.html"&gt;Using ports with resource request&lt;/a&gt; will be updated accordingly.
Also the Limitations section of the neutron admin guide
&lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/admin/config-qos-min-bw.html"&gt;Quality of Service Guaranteed Minimum Bandwidth&lt;/a&gt; needs to be updated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated to show the remaining scope for Ussuri.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>libvirt: Supporting multiple vGPU types for a single pGPU</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/vgpu-multiple-types.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/vgpu-multiple-types"&gt;https://blueprints.launchpad.net/nova/+spec/vgpu-multiple-types&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/add-support-for-vgpu.html"&gt;Virtual GPUs in Nova&lt;/a&gt; was implemented in Queens but only with one supported
GPU type per compute node. Now that GPUs are created as
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/approved/nested-resource-providers.html"&gt;Nested Resource Providers&lt;/a&gt; this spec is only targeting about how to expose
some operator choice for telling which GPU type should be set per GPU.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As Xen provides a specific feature where physical GPUs supporting same vGPU
type are within a single pGPU group, that virt driver doesn’t need to know
which exact pGPUs need to support a specific type, hence this spec only
targets the libvirt driver.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As of now, although multiple GPU types can be proposed for the users, there is
a current limitation where a single GPU device can only accept one type for all
the virtual devices &lt;em&gt;per graphical processing unit&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, NVidia GRID physical cards can accept a list of different GPU
types, but the driver can only support &lt;a class="reference external" href="https://docs.nvidia.com/grid/10.0/grid-vgpu-user-guide/index.html#homogeneous-grid-vgpus"&gt;one type per physical GPU&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="align-default"&gt;
&lt;img alt="https://docs.nvidia.com/grid/10.0/grid-vgpu-user-guide/graphics/sample-vgpu-configurations-grid-2gpus-on-card.png" src="https://docs.nvidia.com/grid/10.0/grid-vgpu-user-guide/graphics/sample-vgpu-configurations-grid-2gpus-on-card.png"/&gt;
&lt;/figure&gt;
&lt;p&gt;Consequently, we require a way to instruct the libvirt driver which vGPU types
an NVIDIA or Intel physical GPU is configured to accept.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;An operator needs a way to inform the libvirt driver which vGPU types an
NVIDIA or Intel physical GPU is configured to accept.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We already have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[devices]/enabled_vgpu_types&lt;/span&gt;&lt;/code&gt; that define which types the
Nova compute node can use:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enabled_vgpu_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;str_vgpu_type_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str_vgpu_type_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now we propose that libvirt will accept configuration sections that are related
to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[devices]/enabled_vgpu_types&lt;/span&gt;&lt;/code&gt; and specifies which exact pGPUs are
related to the enabled vGPU types and will have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;device_addresses&lt;/span&gt;&lt;/code&gt; option
defined like this:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'device_addresses'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;List of physical PCI addresses to associate with a specific GPU type.&lt;/span&gt;

&lt;span class="s2"&gt;The particular physical GPU device address needs to be mapped to the vendor&lt;/span&gt;
&lt;span class="s2"&gt;vGPU type which that physical GPU is configured to accept. In order to&lt;/span&gt;
&lt;span class="s2"&gt;provide this mapping, there will be a CONF section with a name corresponding&lt;/span&gt;
&lt;span class="s2"&gt;to the following template: "vgpu_type_&lt;/span&gt;&lt;span class="si"&gt;%(vgpu_type_name)s&lt;/span&gt;

&lt;span class="s2"&gt;The vGPU type to associate with the PCI devices has to be the section name&lt;/span&gt;
&lt;span class="s2"&gt;prefixed by ``vgpu_``. For example, for 'nvidia-11', you would declare&lt;/span&gt;
&lt;span class="s2"&gt;``[vgpu_nvidia-11]/device_addresses``.&lt;/span&gt;

&lt;span class="s2"&gt;Each vGPU type also has to be declared in ``[devices]/enabled_vgpu_types``.&lt;/span&gt;

&lt;span class="s2"&gt;Related options:&lt;/span&gt;

&lt;span class="s2"&gt;* ``[devices]/enabled_vgpu_types``&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For example, it would be set in nova.conf:&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[devices]&lt;/span&gt;
&lt;span class="na"&gt;enabled_vgpu_types&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;nvidia-35,nvidia-36&lt;/span&gt;
&lt;span class="k"&gt;[vgpu_nvidia-35]&lt;/span&gt;
&lt;span class="na"&gt;device_addresses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;0000:84:00.0,0000:85:00.0&lt;/span&gt;
&lt;span class="k"&gt;[vgpu_nvidia-36]&lt;/span&gt;
&lt;span class="na"&gt;device_addresses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;0000:86:00.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This proposal is very similar to the existing dynamic options we have
with &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/rocky/implemented/numa-aware-vswitches.html#configuration-options"&gt;NUMA-aware vSwitches&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In that case, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nvidia-35&lt;/span&gt;&lt;/code&gt; vGPU type would be supported by the physical
GPUs that are in the PCI addresses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;0000:84:00.0&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;0000:85:00.0&lt;/span&gt;&lt;/code&gt;, while
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nvidia-36&lt;/span&gt;&lt;/code&gt; vGPU would only be supported by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;0000:86:00.0&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If some operator messes up and provides two types for the same pGPU, an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InvalidLibvirtGPUConfig&lt;/span&gt;&lt;/code&gt; exception will be raised. If the operator forgets
to provide a type for a specific pGPU, then the first type given in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled_vgpu_types&lt;/span&gt;&lt;/code&gt; will be supported, like the existing situation.
If the operator fat-fingers the PCI IDs, then when creating the inventory, it
will return an exception.&lt;/p&gt;
&lt;p&gt;As one single compute could now support multiple vGPU types, asking operators
to provide host aggregates for grouping computes having the same vGPU type
becomes irrelevant. Instead, we need to ask operators to amend their flavors
for specific GPU capabilities if they care of such things, or Placement will
just randomly pick one of the available vGPU types.
For this, we propose to standardize GPU capabilities that are unfortunately
very vendor specific (eg. a CUDA library version support) by having a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.vgpu_capabilities&lt;/span&gt;&lt;/code&gt; module that would translate a vendor-specific
vGPU type into a set of os-traits traits.
If operators want vendor-specific traits, it’s their responsibility to provide
custom traits on the resource providers or ask the community to find a standard
trait that would fit their needs.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could ask the operators to provide those details into a
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/provider-config-file.html"&gt;Provider Configuration File&lt;/a&gt; by adding some additional information that
would be libvirt-specific and telling which GPU type to use for a specific
Resource Provider. That said, this would require us to amend the YAML schema
to allow some extra random parameter to be available which would be
libvirt-specific and would defeat the purpose of the Provider Configuration
File to be as much generic as possible. It’s also worth saying that a GPU type
is &lt;em&gt;not&lt;/em&gt; a trait, as it defines quantitative amount of virtual resources to
allocate for a matching physical GPU.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators need to either look at the sysfs (for libvirt) for knowing the
existing pGPUs and which types are supported.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bauzas&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create the config option&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the libvirt virt driver code to make use of that option for creating
the nested Resource Provider inventories.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Classic unittests and functional tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A release note will be added with a ‘feature’ section, and the
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/virtual-gpu.html"&gt;Virtual GPU&lt;/a&gt; documentation will be modified to explain the new feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Virtual instance rescue with boot from volume instances</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/virt-bfv-instance-rescue.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virt-bfv-instance-rescue"&gt;https://blueprints.launchpad.net/nova/+spec/virt-bfv-instance-rescue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Building on the existing stable disk device rescue spec &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; this spec will
introduce support for rescuing boot from volume (BFV) instances and detail the
impact this will have on the API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The original instance rescue implementation included a check in the compute API
to block any requests to rescue instances where the root BDM is a cinder volume
&lt;a class="footnote-reference brackets" href="#id8" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Any such request would be rejected initially by an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNotRescuable&lt;/span&gt;&lt;/code&gt; exception being raised back to the API that would then
result in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; error being returned to the caller.&lt;/p&gt;
&lt;p&gt;Given the work being carried out as part of the stable disk device rescue spec
&lt;a class="footnote-reference brackets" href="#id7" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; we are now able to correctly wire up all disks during an instance rescue
and as a result can remove this check, accepting requests to rescue BFV
instances.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Tenant users would like to rescue BFV instances.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The work outlined in the stable disk device rescue spec &lt;a class="footnote-reference brackets" href="#id7" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; will already allow
Nova to correctly wire up root cinder volumes during a rescue while booting
from the rescue device.&lt;/p&gt;
&lt;p&gt;The only additional changes required to allow us to remove the current BFV
instance check from the compute API are a new compatibility trait, update to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_rescue_image&lt;/span&gt;&lt;/code&gt; within the compute manager and a new API microversion.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_RESCUE_BFV&lt;/span&gt;&lt;/code&gt; trait will be introduced to os-traits, allowing a
compatibility check within the compute API to ensure the target compute service
is capable of rescuing BFV instances.&lt;/p&gt;
&lt;p&gt;In the compute manager &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_rescue_image&lt;/span&gt;&lt;/code&gt; will be extended to attempt to
find a reference to the original image when a rescue image is not provided but
the instance is BFV. An &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNotRescuable&lt;/span&gt;&lt;/code&gt; exception will be raised if no
reference to the original can be found as we can’t boot from the original root
disk as a rescue device while also attaching it again to the instance during a
rescue.&lt;/p&gt;
&lt;p&gt;A new API microversion will be introduced to signal the change in behaviour
from the existing rescue implementation where attempts to rescue BFV instances
were rejected.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;A new microversion will be introduced to signal the change in behaviour from
the original implementation. No other changes will be made to the API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users attempting to use this feature will need to opt-in by using the newly
introduced microversion or later.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_RESCUE_BFV&lt;/span&gt;&lt;/code&gt; compatibility trait will be used to ensure the
target compute service is capable of performing the requested rescue against a
BFV instance within the compute API. If this is not set the existing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNotRescuable&lt;/span&gt;&lt;/code&gt; exception will be raised back to the API resulting in
a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;400&lt;/span&gt;&lt;/code&gt; error being returned to the caller.&lt;/p&gt;
&lt;p&gt;The new microversion or later will be used by callers to opt-in to this new
behaviour. If this isn’t provided the original behaviour of rejecting requests
to rescue BFV instances will be used.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Complete the initial stable device rescue spec. &lt;a class="footnote-reference brackets" href="#id7" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_RESCUE_BFV&lt;/span&gt;&lt;/code&gt; trait to os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start reporting this trait from Nova’s Libvirt driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new microversion signalling the API behaviour change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start using the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_RESCUE_BFV&lt;/span&gt;&lt;/code&gt; trait and microversion in the REST
API to determine when to allow the Compute API to rescue a BFV instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;As highlighted throughout this spec this all requires the initial stable disk
device rescue spec &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to land before this could be implemented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Tempest and functional tests will be introduced to fully validate this new
behaviour.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new microversion will be documented and the existing rescue API
documentation updated to reference it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Virtual instance rescue with stable disk devices &lt;a class="reference external" href="https://review.opendev.org/#/c/693849/"&gt;https://review.opendev.org/#/c/693849/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;BFV instance compute API check &lt;a class="reference external" href="https://github.com/openstack/nova/blob/7aa88029bbf6311033457c32801963da01e88ecb/nova/compute/api.py#L4044-L4053"&gt;https://github.com/openstack/nova/blob/7aa88029bbf6311033457c32801963da01e88ecb/nova/compute/api.py#L4044-L4053&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id9"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>Virtual instance rescue with stable disk devices</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/virt-rescue-stable-disk-devices.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/virt-rescue-stable-disk-devices"&gt;https://blueprints.launchpad.net/nova/+spec/virt-rescue-stable-disk-devices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This will provide the ability to indicate that the rescue disk image
should be attached as a transient disk device (ie USB stick), so that
existing storage attached to an instance doesn’t change its device
address during rescue mode.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When an instance is booted normally there are a number of possible disks
that will be attached to the instance&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An ephemeral or persistent cinder volume root disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero or more ephemeral non-root disks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero or more persistent non-root cinder volumes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An optional swap disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An optional config drive disk&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When the instance is booted in rescue mode though, this storage setup
changes significantly, and differently depending on virt drivers. In
the Libvirt driver, the rescue instance gets:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A rescue root disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The original root disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An optional config drive disk&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are multiple problems with this. First of all several of the disks
are missing entirely, eg the ephemeral non-root disks, all cinder volumes
and the swap disk. This missing storage limits the scope of work the admin
can do in rescue mode.&lt;/p&gt;
&lt;p&gt;The rescue root disk is put on a device that previously held the real
root disk. For example the rescue root is /dev/vda and the real root image is
now shifted to a different device /dev/vdb. Although a well designed
OS setup should not rely on the root device appearing at a fixed device
name, some OSes none the less do depend on this. Moving the root disk
during rescue mode can thus introduce problems of its own, and in fact
contribute to mistakes in rescue mode. For example it may confuse the admin
into setting up their fstab to refer to /dev/vdb, when the root disk will go
back to /dev/vda after rescue mode is finished.&lt;/p&gt;
&lt;p&gt;This change in disk presence during rescue mode is very different to
what happens to disks on a baremetal machine when booted from rescue
media. This means that admin knowledge from working in a bare metal
world needs to be re-learned for OpenStack rescue mode, which adds an
undesirable learning burden for the admin.&lt;/p&gt;
&lt;p&gt;When disks change what address they appear at, this can cause upset
licensing checks of some guests OS too. For example, if hardware
devices change their address too frequently, Windows may decide to
ask for license re-activation. This is again an undesirable thing
for admins in general.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;When the tenant user boots a VM in rescue mode they expect the existing
storage device configuration to be identical to that seen when running
in normal mode, but with an extra transient disk hotplugged to represent
the rescue media.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec will not cover the removal of the current boot from volume check in
the compute API that currently blocks any attempt to rescue an instance using a
root cinder volume. The removal of this check and subsequent impact on the
overall API will be covered in a follow up spec.&lt;/p&gt;
&lt;p&gt;The compute manager code will be changed such that when rescue is performed the
full block device mapping will be present. This will allow instances to be
configured with the full set of non-root cinder volumes that would appear
during normal boot.&lt;/p&gt;
&lt;p&gt;New image properties have already been introduced during Ocata &lt;a class="footnote-reference brackets" href="#id4" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; that will
be used to indicate the type of device and associated bus to use as the rescue
device.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;hw_rescue_bus=virtio|ide|usb|scsi&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hw_rescue_device=disk|floppy|cdrom&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If omitted, the virt driver will default to whatever behaviour it currently
has for setting up the rescue disk. For the Libvirt driver, this means the
default bus would match the hw_disk_bus, and the device type would be “disk”.&lt;/p&gt;
&lt;p&gt;The expected recommended setup would be to tag the rescue image in glance
with hw_rescue_bus=usb, which would indicate to the virt driver that it
should attach a USB flash drive to the guest, containing the rescue image.
For hypervisors which can’t support this an alternative recommendation would
be to tag the rescue image with hw_rescue_bus=ide and hw_rescue_device=cdrom
to cause a new CDROM device to be exposed with the rescue media.&lt;/p&gt;
&lt;p&gt;The Libvirt nova driver will be changed so that when booting in rescue mode,
all the non-root cinder volumes, local ephemeral non-root disks and swap disks
are present in rescue mode. The rescue root device will be added as the &lt;em&gt;last&lt;/em&gt;
device in the configuration, but will be marked as bootable for the BIOS, so it
takes priority over the existing root device. This relies on KVM/QEMU
supporting the “bootindex” parameter, which all supported versions do. This new
rescue mode would not be supported by Xen, nor LXC.&lt;/p&gt;
&lt;p&gt;Other virt driver maintainers may wish to also implement this blueprint, so
approval should be considered to give blessing to all virt drivers. If other
virt driver maintainers wish to commit to doing this in this cycle the list
of assignees will be updated.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Do nothing is always an option, but the current setup has a number of
undesirable characteristics described earlier.&lt;/p&gt;
&lt;p&gt;An alternative might be to simply hardcode a different approach. eg when
using KVM simply always use a USB flash device as the rescue media, and
don’t bother with supporting an image property. This is certainly a viable
option, and if it were not for the sake of maintaining backwards compatibility
with earlier OpenStack, it might even be the preferred approach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None, as the ImageMetaProps object changes have already landed in Ocata &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None, as support for BFV instances will be covered in a separate spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The tenant user will gain the ability to set a new image meta property against
rescue disk images which will indicate the type of disk bus and device to use
when rescuing instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If the admin pre-populates any rescue disk images, they may wish to set the
disk bus and device type to override the historic default behaviour.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Virt driver maintainers can continue to silently ignore the newly introduced
image properties or optionally start using them by implementing this new stable
device approach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Older Libvirt based computes that are not able to honour the stable device
rescue image properties will continue to silently ignore them as they have
since these were introduced during Ocata &lt;a class="footnote-reference brackets" href="#id4" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Once upgraded to Ussuri they
will then start rescusing instances with a stable device layout.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lyarwood (Libvirt impl)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;lyarwood&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Extend the compute manager rescue code to handle the full block device mapping
including non-root cinder volume attachments.&lt;/p&gt;
&lt;p&gt;Extend the nova Libvirt driver to setup all disks when running in rescue
mode.&lt;/p&gt;
&lt;p&gt;Extend the nova Libvirt driver to honour the new image meta properties in
rescue mode disk config.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;A new tempest Libvirt feature configurable and test will be used to validate
correct operation of the new code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new image properties should be documented, and any information about
rescue mode should be updated to explain how disks appear.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;hw_rescue_device and hw_rescue_bus image properties &lt;a class="reference external" href="https://review.opendev.org/#/c/270285/"&gt;https://review.opendev.org/#/c/270285/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/230442/"&gt;https://review.opendev.org/#/c/230442/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/273122/"&gt;https://review.opendev.org/#/c/273122/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id11"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/510106/"&gt;https://review.opendev.org/#/c/510106/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id12"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/651151/"&gt;https://review.opendev.org/#/c/651151/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id13"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Mitaka&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced &lt;a class="footnote-reference brackets" href="#id5" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Newton&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed &lt;a class="footnote-reference brackets" href="#id6" id="id10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Queens&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed &lt;a class="footnote-reference brackets" href="#id7" id="id11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed &lt;a class="footnote-reference brackets" href="#id8" id="id12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>VM Scoped SR-IOV NUMA Affinity Policies</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/implemented/vm-scoped-sriov-numa-affinity.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/vm-scoped-sriov-numa-affinity"&gt;https://blueprints.launchpad.net/nova/+spec/vm-scoped-sriov-numa-affinity&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the Queens release &lt;a class="footnote-reference brackets" href="#id6" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; support was added to allow PCI NUMA affinity
policies to be specified via PCI aliases. This work builds on a previous
feature introduced in the Juno release &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; that introduced strict NUMA
affinity for PCI devices; however, the Queens feature did not address
the NUMA affinity of neutron SR-IOV interfaces which were also enforced by
the original Juno enhancement. This spec seeks to provide a per-VM mechanism
to set a VM-wide NUMA afinity policy for all PCI passthrough devices,
including but not limited to neutron SR-IOV interfaces
(vnic_type=direct,direct-phyical,macvtap,virtio-forwarder)&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In some environments the server form factor is restricted, preventing PCI
devices from being physically installed across all NUMA nodes on a server,
e.g. high density blade/multi server systems or non standard form factor
equipment. In such an environment the default legacy policy which is applied
to all neutron SR-IOV interfaces prevents VMs from using SR-IOV on a non local
NUMA node if the VM has a NUMA topology (uses cpu pinning, vPMEM, hugepages or
requests a NUMA topology explicitly).&lt;/p&gt;
&lt;p&gt;To use a remote SR-IOV device via neutron ports in such an environment the
operator is forced to either configure the guest to have multiple NUMA nodes
or disable NUMA reporting on the host server. Both options pessimize the
performance of both the guest and host in different ways. While a VM with
multiple virtual NUMA nodes can outperform a VM with the same resources and a
single NUMA node in a memory bound workload, that is only true if the workload
is NUMA-aware. A two-node NUMA topology, if enforced on a workload that is not
NUMA-aware, can result in increased cross-NUMA traffic and result in a lower
throughput. Similarly while disabling NUMA reporting at the hardware level
is beneficial in some HPC workloads due to the increased memory bandwidth, it
comes at the cost of increased memory latency, making it unsuitable for
realtime workloads such as VOIP.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator deploying openstack on high density or restricted form factor
hardware, I wish to specify a per-VM NUMA affinity policy for SR-IOV devices
via standard flavor extra specs.&lt;/p&gt;
&lt;p&gt;As a tenant or VNF vendor, I want to be able to customize the affinity of my
VMs via image properties so I can express the NUMA affinity requirements of
my workloads.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes extending the PCI NUMA affinity polices introduced
by &lt;a class="footnote-reference brackets" href="#id6" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to all PCI and SR-IOV devices including neutron ports by adding a
new flavor extra spec &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; image metadata property.&lt;/p&gt;
&lt;p&gt;The new properties will accept one of three values: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;preferred&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;legacy&lt;/span&gt;&lt;/code&gt; as defined in &lt;a class="footnote-reference brackets" href="#id6" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. If a PCI device is requested using a flavor
alias, the NUMA affinity policy specified in the flavor or image will
take precedence over any policy set in the host PCI alias. If no
PCI NUMA affinity policy is specified in the flavor or image, alias based
PCI pass-through will fall back to the policy set in the alias. If no policy
is set in the flavor or image and no policy is set in the alias the legacy
policy will continue to be used. For neutron SR-IOV interfaces if no policy
is set in the flavor or image the legacy policy will be used.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The Queens spec &lt;a class="footnote-reference brackets" href="#id6" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; originally contained both of the proposed flavor
and image properties but were removed during implementation as the original
neutron port usecase that motivated the feature was not captured in the spec.
As a result, while the Queens feature addressed NUMA affinity for
flavor-based PCI pass-through, no mechanism is available to specify the policy
for neutron SR-IOV interfaces.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could change the default policy to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;preferred&lt;/span&gt;&lt;/code&gt; if no policy is specified.
This would optimize for cases where people do not care about NUMA affinity
at the expense of requiring those who do to specify a policy.
As this would be a change in behavior on upgrade it is not proposed that we
take this approach.&lt;/p&gt;
&lt;p&gt;We could enable per-interface NUMA affinity polices. This is not mutually
exclusive with this proposal and will be proposed separately as an additional
feature. The flavor- and image-based approach covers 80% of the use cases
enabled by per-interface NUMA affinity polices without requiring neutron api
changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The image metadata object and related notification objects will be updated
to contain the new PCI NUMA affinity field. As the PCI request spec object
already has a NUMA affinity policy field for alias-based pass-through, no
other data model changes are required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;There will be no direct changes to any existing API. However,
a new flavor extra spec will be introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;The image metadata properties payload will be extended with the
new property field. No other impact is expected.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;To utilize this feature operators and tenants will need to modify their
images and flavors to add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_pci_numa_affinity_policy&lt;/span&gt;&lt;/code&gt;  properties.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;As the scheduler was already asserting legacy PCI affinity, passing
a policy to assert instead should not affect the overall scheduling time.
Depending on the policy selected the performance of the guest may improve
or be reduced inline with the guarantees expressed by that policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;As was previously required to enable NUMA affinity to be enforced for
SR-IOV/PCI devices, the PCI pass-through and NUMA topology filters must be
enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;As this feature relates to SR-IOV it cannot be tested in the upstream gate
via tempest. Unit tests will be provided to assert that the policy
is correctly conveyed to the existing PCI assignment code and the existing
functional test can be extended as required.&lt;/p&gt;
&lt;p&gt;As this feature simply provides another way to specify the PCI affinity policy
the code change is minimal and can leverage much of the existing test coverage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;A release note and updates to the existing user flavor docs will be provided,
and the glance metadefs should be updated to reflect the new image property.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;4&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/share-pci-between-numa-nodes.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/queens/implemented/share-pci-between-numa-nodes.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/juno/approved/input-output-based-numa-scheduling.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/juno/approved/input-output-based-numa-scheduling.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 20 Apr 2020 00:00:00 </pubDate></item><item><title>NUMA Topology with Resource Providers</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/numa-topology-with-rps.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/numa-topology-with-rps"&gt;https://blueprints.launchpad.net/nova/+spec/numa-topology-with-rps&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that &lt;a class="reference internal" href="#nested-resource-providers"&gt;Nested Resource Providers&lt;/a&gt; is a thing in both Placement API and
Nova compute nodes, we could use the Resource Providers tree for explaining
the relationship between a root Resource Provider (root RP) ie. a compute node,
and one or more Non-Uniform Memory Access (NUMA) nodes (aka. cells), each of
them having separate resources, like memory or PCI devices.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec only targets to model resource capabilities for NUMA nodes in some
general and quite abstract manner. We won’t address in this spec how we
should model NUMA-affinized hardware like PCI devices or GPUs and will
discuss these relationships in a later spec.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The NUMATopologyFilter checks a number of resources, including emulator threads
policies, CPU pinned instances and memory page sizes. Additionally, it does two
different verifications :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;whether&lt;/em&gt; some host can fit the query because it has enough capacity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;which&lt;/em&gt; resource(s) should be used for this query (eg. which pCPUs or NUMA
node)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With NUMA topologies modeled as Placement resources, those two questions could
be answered by the Placement service as potential allocation candidates that
the filter would &lt;em&gt;only&lt;/em&gt; be responsible for choosing between them in some
very specific cases (eg. PCI device NUMA affinity, CPU pinning and NUMA
anti-affinity).&lt;/p&gt;
&lt;p&gt;Accordingly, we could model the host memory and the CPU topologies as a set of
resource providers arranged in a tree, and just directly allocate resources for
a specific instance from a resource provider subtree representing a NUMA node
and its resources.&lt;/p&gt;
&lt;p&gt;That said, non resource-related features (like &lt;a class="reference internal" href="#choosing-a-specific-cpu-pin-within-a-numa-node-for-a-vcpu"&gt;choosing a specific CPU pin
within a NUMA node for a vCPU&lt;/a&gt;) would still be only done by the virt driver,
and are not covered by this spec.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Consider the following NUMA topology for a “2-NUMA nodes, 4 cores” host with no
Hyper-Threading:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+--------------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="n"&gt;CN1&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-+---------------+--+---------------+-+&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;NUMA1&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;NUMA2&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;+-+----+-+----+-+&lt;/span&gt;  &lt;span class="o"&gt;+-+----+-+----+-+&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU2&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU3&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CPU4&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="o"&gt;+----+&lt;/span&gt; &lt;span class="o"&gt;+----+&lt;/span&gt;      &lt;span class="o"&gt;+----+&lt;/span&gt; &lt;span class="o"&gt;+----+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here, CPU1 and CPU2 would share the same memory through a common memory
controller, while CPU3 and CPU4 would share their own memory.&lt;/p&gt;
&lt;p&gt;Ideally, applications that require low-latency memory access from multiple
vCPUs on the same instance (for parallel computing reasons) would like to
ensure that those CPU resources are provided by the same NUMA node, or some
performance penalties would occur (if your application is CPU-bound or
I/O-bound of course). For the moment, if you’re an operator, you can use flavor
extra specs to indicate a desired guest NUMA topology for your instance like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor set FLAVOR-NAME \
    --property hw:numa_nodes=FLAVOR-NODES \
    --property hw:numa_cpus.N=FLAVOR-CORES \
    --property hw:numa_mem.N=FLAVOR-MEMORY
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;See all the &lt;a class="reference internal" href="#numa-possible-extra-specs"&gt;NUMA possible extra specs&lt;/a&gt; for a flavor.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The example above is only needed when you want to not evenly divide your
virtual CPUs and memory between NUMA nodes, of course.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Given there are a lot of NUMA concerns, let’s do an iterative approach about
the model we agree.&lt;/p&gt;
&lt;section id="numa-nodes-being-nested-resource-providers"&gt;
&lt;h3&gt;NUMA nodes being nested Resource Providers&lt;/h3&gt;
&lt;p&gt;Given virt drivers can amend a provider tree given by the compute node
ResourceTracker, then the libvirt driver could create child providers for each
of the 2 sockets representing separate NUMA node.&lt;/p&gt;
&lt;p&gt;Since CPU resources are tied to a specific NUMA node, it makes sense to model
the corresponding resource classes as part of the child NUMA Resource
Providers. In order to facilitate querying NUMA resources, we propose to
decorate the NUMA child resource providers with a specific trait named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NUMA_ROOT&lt;/span&gt;&lt;/code&gt; that would be on each NUMA &lt;em&gt;node&lt;/em&gt;. That would help to know
which hosts would be &lt;em&gt;NUMA-aware&lt;/em&gt; and which others are not.&lt;/p&gt;
&lt;p&gt;Memory is a bit tougher to represent. The granularity of a NUMA node having
an amount of attached memory is somehow a first approach but we’re missing the
point that the smallest allocatable unit you can assign with Nova is
really a page size. Accordingly, we should rather model our NUMA subtree
with children Resource Providers that represent the smallest unit of memory
you can allocate, ie. a page size. Since a pagesize is not a &lt;em&gt;consumable&lt;/em&gt;
amount but rather a &lt;em&gt;qualitative&lt;/em&gt; information that helps us to allocate
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; resources, we propose three traits :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;&lt;/code&gt; would allow us to
know whether the memory page size is default or optionally configured.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CUSTOM_MEMORY_PAGE_SIZE_&amp;lt;X&amp;gt;&lt;/span&gt;&lt;/code&gt; where &amp;lt;X&amp;gt; is an integer would allow us to
know the size of the page in KB. To make it clear, even if the trait is a
custom one, it’s important to have a naming convention for it so the
scheduler could ask about page sizes without knowing all the traits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;                                &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
                                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CN_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;
                                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;DISK_GB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
                                &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
                                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;traits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
                                &lt;span class="o"&gt;+--+---------------------------++&lt;/span&gt;
                                   &lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;
                                   &lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;+-------------------------+&lt;/span&gt;                   &lt;span class="o"&gt;+--------------------------+&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NUMA_NODE_O&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;NUMA_NODE_1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;+-------------------------+&lt;/span&gt;                   &lt;span class="o"&gt;+--------------------------+&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="o"&gt;+-------------------+-----+&lt;/span&gt;                   &lt;span class="o"&gt;+--------------------------+&lt;/span&gt;
              &lt;span class="o"&gt;/&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;    \                                          &lt;span class="o"&gt;/+&lt;/span&gt;\
              &lt;span class="o"&gt;+&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;     \&lt;span class="n"&gt;_____________________________&lt;/span&gt;          &lt;span class="o"&gt;.......&lt;/span&gt;
              &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;                                   \
&lt;span class="o"&gt;+-------------+-----------+&lt;/span&gt;   &lt;span class="o"&gt;+-+--------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RP_UUID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RP_UUID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RP_UUID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10240&lt;/span&gt;               &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_4&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_2048&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_1048576&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+----------------------------+&lt;/span&gt;   &lt;span class="o"&gt;+-------------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As we said above, we don’t want to support children PCI devices for Ussuri
at the moment. Other current children RPs for a root compute node, like
ones for VGPU resources or bandwidth resources would still have their
parent be the compute node.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="numa-rp"&gt;
&lt;h3&gt;NUMA RP&lt;/h3&gt;
&lt;p&gt;Resource Provider names for NUMA nodes shall follow a convention of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nodename_NUMA#&lt;/span&gt;&lt;/code&gt; where nodename would be the hypervisor hostname (given by
the virt driver) and where NUMA# would literally be a string made of ‘NUMA’
postfixed by the NUMA cell ID which is provided by the virt driver.&lt;/p&gt;
&lt;p&gt;Each NUMA node would be then a child Resource Provider, having two resource
classes :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;: for telling how many virtual cores (not able to be pinned) the NUMA
node has.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;: for telling how many possible pinned cores the NUMA node has.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A specific trait should be decorating it as we explained : &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NUMA_ROOT&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="memory-pagesize-rp"&gt;
&lt;h3&gt;Memory pagesize RP&lt;/h3&gt;
&lt;p&gt;Each &lt;a class="reference internal" href="#numa-rp"&gt;NUMA RP&lt;/a&gt; should have child RPs for each possible memory page
size per host, and having a single resource class :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt;: for telling how much memory the NUMA node has in that specific
page size.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This RP would be decorated by two traits :&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;either &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;&lt;/code&gt; (default if not configured) or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;&lt;/code&gt; (if large pages are configured)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the size of the page size : CUSTOM_MEMORY_PAGE_SIZE_# (where # is the size
in KB - default to 4 as the kernel defaults to 4KB page sizes)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="compute-node-rp"&gt;
&lt;h3&gt;Compute node RP&lt;/h3&gt;
&lt;p&gt;The root Resource Provider (ie. the compute node) would only provide resources
for classes that are not NUMA-related. Existing children RPs for vGPUs or
bandwidth-aware resources should still have this parent (until we discuss
about NUMA affinity for PCI devices).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="optionally-configured-numa-resources"&gt;
&lt;h3&gt;Optionally configured NUMA resources&lt;/h3&gt;
&lt;p&gt;Given there are NUMA workloads but also non-NUMA workloads, it’s also important
for operators to just have compute nodes accepting the latter.
That said, having the compute node resources to be split between multiple
NUMA nodes could be a problem for those non-NUMA workloads if they want to keep
the existing behaviour.&lt;/p&gt;
&lt;p&gt;For example, say an instance with 2 vCPUs and one host having 2 NUMA nodes but
each one only accepting one VCPU, then the Placement API wouldn’t accept that
host (given each nested RP only accepts one VCPU). For that reason, we need to
have a configuration for saying which resources should be nested.
To reinforce the above, that means a host would be either NUMA or non-NUMA,
hence non-NUMA workloads being set on a specific NUMA node if host is set so.
The proposal we make here will be :&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enable_numa_reporting_to_placement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Ussuri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For below, we will tell hosts as “NUMA-aware” ones that have this option be
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;. For hosts that have this option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; they are explicitely
asked to have a legacy behaviour and will be called “non-NUMA-aware”.&lt;/p&gt;
&lt;p&gt;Depending on the value of the option, Placement would accept or not a host
for the according request. The resulting matrix can be:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+----------------------------------------+----------+-----------+----------+
| ``enable_numa_reporting_to_placement`` | ``None`` | ``False`` | ``True`` |
+========================================+==========+===========+==========+
| NUMA-aware flavors                     | Yes      | No        | Yes      |
+----------------------------------------+----------+-----------+----------+
| NUMA-agnostic flavors                  | Yes      | Yes       | No       |
+----------------------------------------+----------+-----------+----------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Yes&lt;/span&gt;&lt;/code&gt; means that there could be allocation candidates from this host,
while &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;No&lt;/span&gt;&lt;/code&gt; means that no allocation candidates will be returned.&lt;/p&gt;
&lt;p&gt;In order to distinghish compute nodes that have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; value instead of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;, we will decorate the former with a specific trait name
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NON_NUMA&lt;/span&gt;&lt;/code&gt;. Accordingly, we will query Placement by adding this forbidden
trait for &lt;em&gt;not&lt;/em&gt; getting nodes that operators explicitly don’t want them to
support NUMA-aware flavors.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;By default, the value for that configuration option will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; for
upgrade reasons. By the Ussuri timeframe, operators will have to decide
which hosts they want to support NUMA-aware instances and which should be
dedicated for ‘non-NUMA-aware’ instances. A &lt;cite&gt;nova-status pre-upgrade check&lt;/cite&gt;
command will be provided that will warn them to decide before upgrading to
Victoria, if the default value is about to change as we could decide later
in this cycle. Once we stop supporting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; (in Victoria or later), the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NON_NUMA&lt;/span&gt;&lt;/code&gt; trait would no longer be needed so we could stop querying
it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since we allow a transition period for helping the operators to decide, we
will also make clear that this is a one-way change and that we won’t
provide a backwards support for turning a NUMA-aware host into a
non-NUMA-aware host.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade impact&lt;/a&gt; section for further details.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since the discovery of a NUMA topology is made by virt drivers, it
makes the population of those nested Resource Providers to necessarly
be done by each virt driver. Consequently, while the above
configuration option is said to be generic, the use of this option
for populating the Resource Providers tree will only be done by
the virt drivers. Of course, a shared module could be imagined for
the sake of consistency between drivers, but this is an
implementation detail.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="the-very-simple-case-i-don-t-care-about-a-numa-aware-instance"&gt;
&lt;h3&gt;The very simple case: I don’t care about a NUMA-aware instance&lt;/h3&gt;
&lt;p&gt;For flavors just asking for, say, vCPUs and memory without asking them to be
NUMA-aware, then we will make a single Placement call asking to &lt;em&gt;not&lt;/em&gt; land
them on a NUMA-aware host:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;resources=VCPU:&amp;lt;X&amp;gt;,MEMORY_MB=&amp;lt;Y&amp;gt;
&amp;amp;required=!HW_NUMA_ROOT
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case, even if NUMA-aware hosts have enough resources for this query,
the Placement API won’t provide them but only non-NUMA-aware ones (given the
forbidden &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NUMA_ROOT&lt;/span&gt;&lt;/code&gt; trait).
We’re giving the possibility to the operator to shard their clouds between
NUMA-aware hosts and non-NUMA-aware hosts but that’s not really changing the
current behaviour as of now where operators create aggregates to make sure
non-NUMA-aware instances can’t land on NUMA-aware hosts.&lt;/p&gt;
&lt;p&gt;See the &lt;cite&gt;Upgrade impact&lt;/cite&gt; session for rolling upgrade situations where clouds
are partially upgraded to Ussuri and where only a very few nodes are reshaped.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="asking-for-numa-aware-vcpus"&gt;
&lt;h3&gt;Asking for NUMA-aware vCPUs&lt;/h3&gt;
&lt;p&gt;As NUMA-aware hosts have a specific topology with memory being in a grand-child
RP, we basically need to ensure we can translate the existing expressiveness in
the flavor extra specs into a Placement allocation candidates query that asks
for parenting between the NUMA RP containing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources and the
memory pagesize RP containing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; resources.&lt;/p&gt;
&lt;p&gt;Accordingly, here are some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;none&lt;/span&gt;&lt;/code&gt; as a value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_policy&lt;/span&gt;&lt;/code&gt; which means that in this
example, allocation candidates can all be from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PROC1&lt;/span&gt;&lt;/code&gt; group meaning
that we defeat the purpose of having the resources separated into different
NUMA nodes (which is the purpose of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&lt;/span&gt;&lt;/code&gt;). This is OK
as we will also modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; to only accept
allocation candidates for a host that are in different NUMA nodes.
It will probably be implemented in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.hardware&lt;/span&gt;&lt;/code&gt; module but
that’s an implementation detail.&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=1&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&amp;amp;hw:numa_cpus.0=0,1&amp;amp;hw:numa_cpus.1=2,3,4,5,6,7&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for a flavor of 8 VCPUs, 8GB of RAM and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=2&amp;amp;hw:numa_cpus.0=0,1&amp;amp;hw:numa_mem.0=1024&lt;/span&gt;
&lt;span class="pre"&gt;&amp;amp;hw:numa_cpus.1=2,3,4,5,6,7&amp;amp;hw:numa_mem.1=7168&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7168&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can understand, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; values will be a result
of the division of respectively the flavored vCPUs and the flavored memory by
the value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes&lt;/span&gt;&lt;/code&gt; (which is actually already calculated and
provided as NUMATopology object information in the RequestSpec object).&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The translation mechanism from a flavor-based request into Placement query
will be handled by the scheduler service.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Since memory is provided as grand-child, we need to always ask for a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;&lt;/code&gt; which is the default.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="asking-for-specific-memory-page-sizes"&gt;
&lt;h3&gt;Asking for specific memory page sizes&lt;/h3&gt;
&lt;p&gt;Operators defining a flavor of 2 vCPUs, 4GB of RAM and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=2MB,hw:numa_nodes=2&lt;/span&gt;&lt;/code&gt; will see that the Placement query will
become:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_MEMORY_PAGE_SIZE_2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you only want large page size support without really specifying which size
(eg. by specifying &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=large&lt;/span&gt;&lt;/code&gt; instead of, say, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;2MB&lt;/span&gt;&lt;/code&gt;), then
the above same request for large pages would translate into:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_LARGE&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Asking the same with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=small&lt;/span&gt;&lt;/code&gt; would translate into:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_PAGE_SIZE_SMALL&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And eventually, asking with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_page_size=any&lt;/span&gt;&lt;/code&gt; would mean:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources_PROC1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_PROC2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;resources_MEM2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MEMORY_MB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;required_NUMA2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HW_NUMA_ROOT&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;same_subtree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_PROC2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_MEM2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_NUMA2&lt;/span&gt;
&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;group_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As we said for vCPUs, given we query with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;group_policy=none&lt;/span&gt;&lt;/code&gt;,
allocation candidates would be within the same NUMA node but that’s fine
since we also said that the scheduler filter would then no agree with
them if there is a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:numa_nodes=X&lt;/span&gt;&lt;/code&gt; there.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="the-fallback-case-for-numa-aware-flavors"&gt;
&lt;h3&gt;The fallback case for NUMA-aware flavors&lt;/h3&gt;
&lt;p&gt;In the &lt;a class="reference internal" href="#optionally-configured-numa-resources"&gt;Optionally configured NUMA resources&lt;/a&gt; section, we said that we would
want to accept NUMA-aware flavors to land on hosts that have the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_numa_reporting_to_placement&lt;/span&gt;&lt;/code&gt; option set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt;. Since we can’t
yet build a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OR&lt;/span&gt;&lt;/code&gt; query for allocation candidates, we propose to make another
call to Placement.
In this specific call (we name it a fallback call), we want to get all
non-reshaped nodes that are &lt;em&gt;not&lt;/em&gt; explicitly said to not support NUMA.
In this case, the request is fairly trivial since we decorated them with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_NON_NUMA&lt;/span&gt;&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;resources=VCPU:&amp;lt;X&amp;gt;,MEMORY_MB=&amp;lt;Y&amp;gt;
&amp;amp;required=!HW_NON_NUMA,!HW_NUMA_ROOT
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then we would get all compute nodes that have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; value (
including nodes that are still running the Train release in a rolling upgrade
fashion).&lt;/p&gt;
&lt;p&gt;Of course, we would get nodes that could potentially &lt;em&gt;not&lt;/em&gt; accept the
NUMA-aware flavor but we rely on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; for not selecting
them, exactly like what we do in Train.&lt;/p&gt;
&lt;p&gt;There is some open question about whether we should do the fallback call only
if the NUMA-specific call is not getting candidates or if we should generate
the two calls either way and merge the results.
The former is better for performance reasons since we avoid a potentially
unnecessary call but would generate some potential spread/pack affinity issues.
Here we all agree on the fact we can leave the question unresolved for now and
defer the resolution to the implementation phase.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Modeling of NUMA resources could be done by using specific NUMA resource
classes, like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMA_VCPU&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMA_MEMORY_MB&lt;/span&gt;&lt;/code&gt; that would only be set for
children NUMA resource providers, and where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEMORY_MB&lt;/span&gt;&lt;/code&gt; resource
classes would only be set on the root Resource Provider (here the compute
node).&lt;/p&gt;
&lt;p&gt;If the Placement allocations candidates API was also able to provide a way to
say ‘you can split the resources between resource providers’, we wouldn’t need
to carry a specific configuration option for a long time. All hosts would then
be reshaped to be NUMA-aware but then non-NUMA-aware instances could
potentially land on those hosts. That wouldn’t change the fact that for
optimal capacity, operators need to shard their clouds between NUMA workloads
and non-NUMA ones, but from a Placement perspective, all hosts would be equal.
This alternative proposal has largely already been discussed in a
spec but the outcome consensus was that it was very
difficult to implement and potentially not worth the difficulty.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None, flavors won’t need to be modified since we will provide a translation
mechanism. That said, we will explicitly explain in the documentation that
we won’t support any placement-like extra specs in flavors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Only when changing the configuration option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, a reshape is done.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Operators would want to migrate some instances from hosts to anothers before
explicitely enabling or disabling NUMA awareness on their nodes since they will
have to consider the capacity usage accordingly as they will have to shard
their cloud. This being said, this would only be necessary for clouds that
weren’t yet already dividing NUMA-aware and non-NUMA-aware workloads between
hosts thru aggregates.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None, except virt driver maintainers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;As described above, in order to prevent a flavor update during upgrade, we will
provide a translation mechanism that will take the existing
flavor extra spec properties and transform them into Placement numbered groups
query.&lt;/p&gt;
&lt;p&gt;Since there will be a configuration option for telling that a host would become
NUMA-aware, the corresponding allocations accordingly have to change hence the
virt drivers be responsible for providing a reshape mechanism that will
eventually call the &lt;a class="reference internal" href="#placement-api-reshaper-endpoint"&gt;Placement API /reshaper endpoint&lt;/a&gt; when starting the
compute service. This reshape implementation will absolutely need to consider
the Fast Forward Upgrade (FFU) strategy where all controlplane is down and
should possibly document any extra step required for FFU with an eventual
removal in a couple of releases once all deployers no longer need this support.&lt;/p&gt;
&lt;p&gt;Last but not the least, we will provide a transition period (at least during
the Ussuri timeframe) where operators can decide which hosts to dedicate to
NUMA-aware workloads. A specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt; &lt;span class="pre"&gt;pre-upgrade&lt;/span&gt; &lt;span class="pre"&gt;check&lt;/span&gt;&lt;/code&gt; command
will warn them to do so before upgrading to Victoria.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;bauzas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;p&gt;bauzas&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;libvirt driver passing NUMA topology through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hyper-V driver passing NUMA topology through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree()&lt;/span&gt;&lt;/code&gt; API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Possible work on the NUMATopologyFilter to look at the candidates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scheduler translating flavor extra specs for NUMA properties into Placement
queries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-status&lt;/span&gt; &lt;span class="pre"&gt;pre-upgrade&lt;/span&gt; &lt;span class="pre"&gt;check&lt;/span&gt;&lt;/code&gt; command&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Functional tests and unittests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="nested-resource-providers"&gt;Nested Resource Providers&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/queens/approved/nested-resource-providers.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/queens/approved/nested-resource-providers.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="choosing-a-specific-cpu-pin-within-a-numa-node-for-a-vcpu"&gt;choosing a specific CPU pin within a NUMA node for a vCPU&lt;/span&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/cpu-topologies.html#customizing-instance-cpu-pinning-policies"&gt;https://docs.openstack.org/nova/latest/admin/cpu-topologies.html#customizing-instance-cpu-pinning-policies&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="numa-possible-extra-specs"&gt;NUMA possible extra specs&lt;/span&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/flavors.html#extra-specs-numa-topology"&gt;https://docs.openstack.org/nova/latest/admin/flavors.html#extra-specs-numa-topology&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="huge-pages"&gt;Huge pages&lt;/span&gt;: &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/huge-pages.html"&gt;https://docs.openstack.org/nova/latest/admin/huge-pages.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="placement-api-reshaper-endpoint"&gt;Placement API /reshaper endpoint&lt;/span&gt;: &lt;a class="reference external" href="https://developer.openstack.org/api-ref/placement/?expanded=id84-detail#reshaper"&gt;https://developer.openstack.org/api-ref/placement/?expanded=id84-detail#reshaper&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="placement-can-split"&gt;Placement can_split&lt;/span&gt;: &lt;a class="reference external" href="https://review.opendev.org/#/c/658510/"&gt;https://review.opendev.org/#/c/658510/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="target" id="physical-cpu-resources"&gt;physical CPU resources&lt;/span&gt;: &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/train/approved/cpu-resources.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Mon, 17 Feb 2020 00:00:00 </pubDate></item><item><title>Support multiple stores of Glance</title><link>https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/support-glance-multiple-backend.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-glance-multiple-backend"&gt;https://blueprints.launchpad.net/nova/+spec/support-glance-multiple-backend&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposed to support the multiple backend of glance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In Train, Glance has added the ability to configure multiple stores
&lt;a class="footnote-reference brackets" href="#id2" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. This way an operator can configure more than one of similar or
different kind of stores and use one as a default store. If a store
is not specified at the time of uploading an image then the image
will be stored in default store.&lt;/p&gt;
&lt;p&gt;In case of Nova snapshot or backup, if no changes are made to Nova, even if
multiple stores are configured then the snapshot or backup image will be
uploaded to default store. This will not cause any issue unless Nova is using
ceph as a backend and glance has configured ceph store as well and default
store in glance is not ceph. This will affect nova’s ability to use ceph
backend for uploading snapshots or backup images in more efficient way.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Operator wants to upload all the snapshots or backup images to one
specific/dedicated store in Glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fast snapshot using ceph even ceph is not a default store in glance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In case if instance is created using image then it stores the image uuid as
‘image_ref’. When instance snapshot or backup is requested nova should
pass the ‘image_ref’ as a header ‘X-OpenStack-Base-Image-Ref’ to glance, so
that glance will identify in which store the base image is stored and use that
same store to upload the instance snapshot or instance backup.&lt;/p&gt;
&lt;p&gt;In case if instance is created using volume then the snapshot or backup image
should be uploaded to default store configured in Glance.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a new microversion to snapshot and backup API to support configuring to
upload the snapshot/backup image to specific store. I am proposing to add
new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--store&lt;/span&gt;&lt;/code&gt; option to snapshot and backup API where user can specify to
which store snapshot/backend image will be uploaded. If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--store&lt;/span&gt;&lt;/code&gt; option
is not specified then the image will be uploaded to default store.&lt;/p&gt;
&lt;p&gt;If user chooses the ‘store’ which is not configured in
glance then glance will return with 404 NotFound error and the image which
is created in ‘queued’ state while ‘snapshot’ or ‘backup’ operation will
be deleted during the cleanup operation. The alternate way is, In the
beginning before creating queued image, validate the ‘store’ specified by
end user using ‘/v2/info/stores’ discovery call of glance. If specified
‘store’ is not present in the discovery response then whole operation will
be skipped with 404 response to end user.&lt;/p&gt;
&lt;p&gt;End user can identify available ‘stores’ in glance using
‘GET $IMAGE_API_URL/v2/info/stores’ discovery call. It will return the
list of stores configured at glance side. The “id” field from the
discovery response represents the configured store. Following is the
example of discover ‘/v2/stores/info’ response call:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET $IMAGE_API_URL/v2/info/stores

{
    "stores": [
        {
            "id":"reliable",
            "description": "Reliable filesystem store"
        },
        {
            "id":"fast",
            "description": "Fast access to rbd store",
            "default": true
        },
        {
            "id":"cheap",
            "description": "Less expensive rbd store"
        }
    ]
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For example glance has two file stores configured as ‘file_1’, ‘file_2’ and
‘file_1’ is set as default store then at present scenario all images of
‘snapshot’or ‘backup’ operation will always be uploaded to ‘file_1’ store of
glance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new configuration option ‘store’ under ‘glance’ section to
upload all the snapshot/backup images to specified/dedicated store. If this
option is not defined then all the snapshot/backup images will be uploaded to
the default store. This solution will be efficient if operator doesn’t want
to expose the use of uploading snapshot image to specific store to end user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;abhishek-kekane&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="feature-liaison"&gt;
&lt;h3&gt;Feature Liaison&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Feature liaison:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Balazs Gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Change glanceclient in nova to pass ‘X-OpenStack-Base-Image-Ref’ header
to upload call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unittest&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/glance/train/admin/multistores.html"&gt;https://docs.openstack.org/glance/train/admin/multistores.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 17 Feb 2020 00:00:00 </pubDate></item><item><title>Add host and hypervisor hostname flag to create server</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/add-host-and-hypervisor-hostname-flag-to-create-server.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/add-host-and-hypervisor-hostname-flag-to-create-server"&gt;https://blueprints.launchpad.net/nova/+spec/add-host-and-hypervisor-hostname-flag-to-create-server&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When admin users specify the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/availability-zones.html"&gt;forced_host/forced_node&lt;/a&gt; to create servers,
nova will bypass the scheduler filters. This spec proposes to add two new
params &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; as specified host and/or node to
create servers without bypassing the scheduler filters in a new REST API
microversion.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When admin users specify the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/availability-zones.html"&gt;forced_host/forced_node&lt;/a&gt; to create servers,
nova will bypass the scheduler filters.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Without scheduler filters, failure instances may waste effort trying to boot
when failure is inevitable because of network provider, PCI device, NUMA
topology, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could be trying to claim resources on the host that aren’t available,
and/or unintentionally over-subscribing the host because without running
the filters we don’t pass down any limits for the resource claim.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;This change adds the following use case to the system:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An admin wants to request that a server is created on a specified compute
host and/or node and have the request validated by the scheduler filters
rather than forced.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; to the REST API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_compute_api:servers:create:requested_destination&lt;/span&gt;&lt;/code&gt; to
limit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; only for admin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Translate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; to a
RequestSpec.requested_destination which still goes through the scheduler
filters.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We still leave the old mechanism &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;az:host:node&lt;/span&gt;&lt;/code&gt; in this new microversion
so users have the option of either forcing the target during server creates
or requesting the target.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There is a filter named &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/configuration/schedulers.html#jsonfilter"&gt;JsonFilter&lt;/a&gt; which is not used by default. This
filter allows simple JSON-based grammar for selecting hosts. If we want to
specify the host named “openstack-node”, we can add the params like this:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--hint&lt;/span&gt; &lt;span class="pre"&gt;query='["=","$host","openstack-node"]'&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In addition to the warnings in the documentation for this filter, if it is
configurable, it may not be present in all clouds and thus can not be
guaranteed for interoperability.&lt;/p&gt;
&lt;p&gt;There is a filter named &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/configuration/schedulers.html#aggregateinstanceextraspecsfilter"&gt;AggregateInstanceExtraSpecsFilter&lt;/a&gt; which is not used
by default. This filter checks that the aggregate metadata satisfies any extra
specifications associated with the instance type (that have no scope or are
scoped with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;aggregate_instance_extra_specs&lt;/span&gt;&lt;/code&gt;). If we want to specify the
host named “openstack-node”, we can create a aggregate named “test-ag01”
include host “openstack-node”. Then we set metadata for this aggregate with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host=openstack-node&lt;/span&gt;&lt;/code&gt;. At last, we create a flavor and set metadata for
this flavor with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;aggregate_instance_extra_specs:host=openstack-node&lt;/span&gt;&lt;/code&gt;. So
when we choose the flavor to create instances, all will be on the host
“openstack-node”.&lt;/p&gt;
&lt;p&gt;In this case, creating an aggregate and flavor pinned to that aggregate for
every host/node in a large cloud is not manageable and would also potentially
leak deployment details about the cloud, and also confuse users when we have
so many availability zones to model those aggregates. It’s just not a
realistic option for this use case in a large cloud.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;In a new microversion add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; flag
to the API, both of them are optional:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;POST /servers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"openstack-node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"hypervisor_hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"openstack-node"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Only show new parameters’ JSON schema definition for body data of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;server&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="s1"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;parameter_types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;
&lt;span class="s1"&gt;'hypervisor_hostname'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;parameter_types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Depending on whether/how the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; is set,
the actions are as followed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; is supplied in the request body, at first Compute API will check
whether we can fetch a compute node for this &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; from DB. If not, an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;Bad&lt;/span&gt; &lt;span class="pre"&gt;Request&lt;/span&gt;&lt;/code&gt; will be returned to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; is supplied in the request body, at first
Compute API will check whether we can fetch a compute node for this
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; from DB. If not, an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;Bad&lt;/span&gt; &lt;span class="pre"&gt;Request&lt;/span&gt;&lt;/code&gt; will
be returned to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; are supplied in the request
body, at first Compute API will check whether we can fetch a compute node
for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt; from DB. If not, an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTP&lt;/span&gt; &lt;span class="pre"&gt;400&lt;/span&gt; &lt;span class="pre"&gt;Bad&lt;/span&gt; &lt;span class="pre"&gt;Request&lt;/span&gt;&lt;/code&gt; will be returned to users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The new (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;host&lt;/span&gt;&lt;/code&gt; and/or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_hostname&lt;/span&gt;&lt;/code&gt;) and the old
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;az:host:node&lt;/span&gt;&lt;/code&gt;) mechanisms are mutually exclusive. If both are specified
in the same request, the API will return an HTTP 400 Bad Request.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Update python-novaclient and python-openstackclient to support the new
microversion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Boxiang Zhu (&lt;a class="reference external" href="mailto:zhu.boxiang%4099cloud.net"&gt;zhu&lt;span&gt;.&lt;/span&gt;boxiang&lt;span&gt;@&lt;/span&gt;99cloud&lt;span&gt;.&lt;/span&gt;net&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new microversion for this change.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Functional and unit test will be provided.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some scenarios (Create a server on a requested host and/or node and then
move it - live migrate, evacuate, cold migrate and unshelve - to make sure
it moves to another host and isn’t restricted to the original requested
destination) will be provided.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The API document should be changed to introduce this new feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Train PTG etherpad: &lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-ptg-train"&gt;https://etherpad.openstack.org/p/nova-ptg-train&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Support adding the reason behind a server lock</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/add-locked-reason.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/add-locked-reason"&gt;https://blueprints.launchpad.net/nova/+spec/add-locked-reason&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently as a part of locking an instance, while we know who locked it we do
not have a way of knowing “why” it was locked. This spec aims at addressing
this question.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When locking a server using the nova lock action there is no provision to set
a description or mention a reason of why it’s being locked. This is often a
much needed information in situations (eg. security/hardware team locking the
server or when an automated job locks the server or an admin locks it and goes
on vacation) when it’s not ideal to just ask the user why it was locked and if
it could be unlocked.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a cloud operator I would like to know why a certain user locked the server
when that user is not contactable or without having to open internal tickets
to find out.&lt;/p&gt;
&lt;p&gt;As an user/admin I would like to add a reason when locking the server like the
date after which it is safe to unlock so that the other admins know this.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes to store the locked_reason as an item in the system metadata
of the instance.&lt;/p&gt;
&lt;p&gt;The request for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; where action is “lock”
will get a new optional argument called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt; by which the user can
specify the reason for locking the instance. If the reason is specified, it
will create the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt; item in the instance_system_metadata for
that instance which will be deleted upon unlocking the instance.&lt;/p&gt;
&lt;p&gt;The plan is to expose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt;  information by adding it as a new key
in the response of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt;  where the action is rebuild and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt; requests. See the &lt;a class="reference internal" href="#rest-api-impact"&gt;REST API impact&lt;/a&gt; section for
more details on how this would be done.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative would be to not have the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; at all for the locking mechanism and just
do this via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt; request.&lt;/p&gt;
&lt;p&gt;Another alternative is to make lock as its &lt;a class="reference external" href="https://review.openstack.org/#/c/206864/1/specs/liberty/approved/add-locking-information-in-server-get-response.rst@55"&gt;own resource&lt;/a&gt; in which case we can
add a new lock API which would look like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}/lock&lt;/span&gt;&lt;/code&gt; that
can include the details like locked or not, locked_by, locked_reason and
timestamp. But we already have a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}/os-instance-actions/{request_id}&lt;/span&gt;&lt;/code&gt; request API to get
the details like timestamp. So it does not make sense to add a whole new API
for just retrieving the locked_reason information.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The request for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; will change since it will
get a new optional argument called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt; which will accept the
reason for locking the server and store this in the instance_system_metadata
table in the database.&lt;/p&gt;
&lt;p&gt;A sample JSON request for locking a server would look like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="s2"&gt;"lock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"locked_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"because I am mad at belmiro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The request body would either be a “null” object in case the reason is not
specified or it will have a “locked_reason” field in the object (possible from
the new microversion).&lt;/p&gt;
&lt;p&gt;We plan to expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt; information through
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt;  where the action is rebuild and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt; REST APIs whose reponses will have that key.&lt;/p&gt;
&lt;p&gt;Currently the response only contains the “locked” key which is of type boolean
that conveys if the instance is locked or not based on if it’s true or false.
We will now also include the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt; key in addition to the locked
key.&lt;/p&gt;
&lt;p&gt;A sample JSON response would look like this for a locked server:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"OS-EXT-STS:task_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"b546af1e-3893-44ea-a660-c6b998a64ba7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ACTIVE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;"locked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"locked_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"foo-test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"surya-probes-001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"OS-EXT-SRV-ATTR:launch_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2018-06-29T15:07:29Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tenant_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"940f47b984034c7f8f9624ab28f5643c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;"host_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"UP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"trusted_image_certificates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that it is the duty of the admin locking the instance to put information
that can be user-visible in the reason because there is no protection there.&lt;/p&gt;
&lt;p&gt;A sample JSON response would look like this for an unlocked server:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"OS-EXT-STS:task_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"b546af1e-3893-44ea-a660-c6b998a64ba7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ACTIVE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;"locked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"locked_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"surya-probes-001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"OS-EXT-SRV-ATTR:launch_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2018-06-29T15:07:29Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tenant_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"940f47b984034c7f8f9624ab28f5643c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="s2"&gt;"host_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"UP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"trusted_image_certificates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Filtering/Sorting: The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked&lt;/span&gt;&lt;/code&gt; key will be added to the existing list of
valid sorting/filtering keys so that instances can be filtered/sorted based
on this field.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The admin locking the instance should take care not to expose information
through the locked_reason that the owner should not know about.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;The InstancePayload object will be updated to include the
“locked_reason” field which can be added to the InstanceActionPayload
notification that would be emitted when locking the instance. This would
require a version bump for the payload notification objects.&lt;/p&gt;
&lt;p&gt;A sample notification for a locked server:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"instance.lock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"payload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"common_payloads/InstanceActionPayload.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"nova_object.data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"locked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"locked_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"foo-test"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"INFO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"publisher_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nova-api:fake-mini"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;In order to be able to provide a reason and then see this when asking for a
server show, python-openstackclient and python-novaclient will be updated:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;to add the new optional parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--reason&lt;/span&gt;&lt;/code&gt; for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; where the action is “lock”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to accommodate the parsing of the new keys in the server
response for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt;  where the action is rebuild and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt; REST APIs from the new microversion.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;tssurya&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Handle &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt; on receiving an optional
“locked_reason” parameter for lock action on the client side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked_reason&lt;/span&gt;&lt;/code&gt; through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt;&lt;/code&gt;  where the
action is rebuild and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;servers/{server_id}&lt;/span&gt;&lt;/code&gt; REST APIs after
setting/deleting the reason while locking/unlocking and bumping the
microversion on the server side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support filtering and sorting servers on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locked&lt;/span&gt;&lt;/code&gt; parameter.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional tests for verifying the functionality. Tempest schema test
for changing the REST API response schema format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the description of the Compute API reference with regards to the
changes in the REST APIs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>libvirt driver launching AMD SEV-encrypted instances</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/amd-sev-libvirt-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/amd-sev-libvirt-support"&gt;https://blueprints.launchpad.net/nova/+spec/amd-sev-libvirt-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec proposes work required in order for nova’s libvirt driver to
support launching of KVM instances which are encrypted using &lt;a class="reference external" href="https://developer.amd.com/sev/"&gt;AMD’s
SEV (Secure Encrypted Virtualization) technology&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;While data is typically encrypted today when stored on disk, it is
stored in DRAM in the clear.  This can leave the data vulnerable to
snooping by unauthorized administrators or software, or by hardware
probing.  New non-volatile memory technology (NVDIMM) exacerbates this
problem since an NVDIMM chip can be physically removed from a system
with the data intact, similar to a hard drive.  Without encryption any
stored information such as sensitive data, passwords, or secret keys
can be easily compromised.&lt;/p&gt;
&lt;p&gt;AMD’s SEV offers a VM protection technology which transparently
encrypts the memory of each VM with a unique key.  It can also
calculate a signature of the memory contents, which can be sent to the
VM’s owner as an attestation that the memory was encrypted correctly
by the firmware.  SEV is particularly applicable to cloud computing
since it can reduce the amount of trust VMs need to place in the
hypervisor and administrator of their host system.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a cloud administrator, in order that my users can have greater
confidence in the security of their running instances, I want to
provide a flavor containing an SEV-specific &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/flavors.html#extra-specs-required-resources"&gt;extra
spec resource requirement&lt;/a&gt;
which will allow users booting instances with that flavor to ensure
that their instances run on an SEV-capable compute host with SEV
encryption enabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a cloud user, in order to not have to trust my cloud operator
with my secrets, I want to be able to boot VM instances with SEV
functionality enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;For Train, the goal is a minimal but functional implementation which
would satisfy the above use cases.  It is proposed that initial
development and testing would include the following deliverables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV capabilities.  Logic is required to check
that the various layers of the hardware and software hypervisor
stack are SEV-capable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The presence of the following XML in the response from a libvirt
&lt;a class="reference external" href="https://libvirt.org/html/libvirt-libvirt-domain.html#virConnectGetDomainCapabilities"&gt;virConnectGetDomainCapabilities()&lt;/a&gt;
API call &lt;a class="reference external" href="https://libvirt.org/git/?p=libvirt.git;a=commit;h=6688393c6b222b5d7cba238f21d55134611ede9c"&gt;indicates that both QEMU and the AMD Secure Processor
(AMD-SP) support SEV functionality&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt; &lt;span class="n"&gt;supported&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;domainCapabilities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This functionality-oriented check should preempt the need for any
version checking in the driver.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/sys/module/kvm_amd/parameters/sev&lt;/span&gt;&lt;/code&gt; should have the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;1&lt;/span&gt;&lt;/code&gt;
to indicate that the kernel has SEV capabilities enabled.  This
should be readable by any user (i.e. even non-root).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that both checks are required, since the presence of the first
does not imply the second.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/resource-classes.html"&gt;resource class&lt;/a&gt;
which represents the number of guests with secure encrypted memory
which a compute host can run concurrently (due to a limited number
of slots for encryption keys in the memory controller).  It will be
zero for hosts which do not support SEV.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV&lt;/span&gt;&lt;/code&gt; trait in
os-traits to indicate that a) it cannot be used yet, only in the
future when SEV support is fully implemented, and b) even at that
point it should not be used via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV=required&lt;/span&gt;&lt;/code&gt;,
because the new resource class should be used instead.&lt;/p&gt;
&lt;p&gt;The trait has been present &lt;a class="reference external" href="https://docs.openstack.org/os-traits/latest/reference/index.html#amd-sev"&gt;since 0.11.0&lt;/a&gt;,
and &lt;a class="reference external" href="https://review.openstack.org/635608"&gt;was added in the Stein cycle&lt;/a&gt; on the basis of the design
in &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/amd-sev-libvirt-support.html"&gt;the previous version of this spec accepted for Stein&lt;/a&gt;.
However since then we have realised that we need to track the SEV
capability as a discretely quantifiable resource rather than as a
binary feature, therefore the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource
class will supersede it as the low-level mechanism for indicating
when an SEV context is required.&lt;/p&gt;
&lt;p&gt;It is regrettable to have to back-pedal on this element of the
design; however nothing used the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV&lt;/span&gt;&lt;/code&gt; trait yet so it
seems very unlikely that this would cause an issue for anyone.  It
will not be removed for two reasons:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;The os-traits project has a policy of never removing any traits,
based on the idea that an extensible-only set of traits is easier
to manage than one which can be shrunk.  For example, a sync of
the traits with the placement database will never need to worry
about removing entries or corresponding foreign keys.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It seems helpful to provide the trait anyway, even though it’s
not strictly required.  In fact &lt;a class="reference external" href="https://review.openstack.org/638680"&gt;the code to do so&lt;/a&gt; is already under review,
so hardly any extra work would be required.&lt;/p&gt;
&lt;p&gt;One use case suggested was implementing anti-affinity of non-SEV
guests with SEV hosts, thereby keeping SEV hosts as free as
possible for SEV guests.  This could be achieved simply by
placing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_AMD_SEV=forbidden&lt;/span&gt;&lt;/code&gt; on all non-SEV
flavors, although a more sophisticated approach might take
advantage of a future implementation of &lt;a class="reference external" href="https://review.openstack.org/609960"&gt;a parallel proposal for
forbidden aggregates&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another use case might be to allow operators and users to
distinguish between multiple mechanisms for encrypting guest
memory available from different vendors within a single cloud,
e.g. if the compute plane contained a mix of machines supporting
AMD SEV and Intel &lt;a class="reference external" href="https://en.wikichip.org/wiki/x86/tme#Multi-Key_Total_Memory_Encryption"&gt;MKTME&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, any implementations of those use cases are outside the
scope of this spec.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the libvirt driver &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update the ProviderTree object&lt;/a&gt;
with the correct inventory for the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt;
resource class.  For example &lt;a class="reference external" href="https://www.redhat.com/archives/libvir-list/2019-January/msg00652.html"&gt;on EPYC machines the maximum number of
SEV guests supported is expected to be 15&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since it is not currently possible to obtain this limit
programmatically via libvirt, introduce a new config option in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]&lt;/span&gt;&lt;/code&gt; section of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt; to set the size of this
inventory for each SEV-capable compute host.  This would default to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; with a forward-looking meaning of “auto-detect the
inventory, or if this is not possible, don’t impose any limit”.
This would have two benefits:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Operators are not forced to make any configuration changes to
take advantage of SEV out of the box.  Guest VMs may fail to
launch if the host’s real capacity is exceeded, but if that
becomes a problem, operators can just set the value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No configuration changes are needed once auto-detection is
introduced.  For example, if auto-detection obtains the same
value as a manually configured limit, a warning could be emitted
deprecating the configuration option, and if it obtained a
different value, an error could be raised, or at least a warning
that the auto-detected value would be used instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="#limitations"&gt;Limitations&lt;/a&gt; section for more information on this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the libvirt driver to include extra XML in the guest’s domain
definition when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; is present in
the flavor extra specs, in order to ensure the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SEV security is enabled via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;launchSecurity&amp;gt;&lt;/span&gt;&lt;/code&gt; element,
as detailed in the &lt;a class="reference internal" href="#sev-launch-time-configuration"&gt;SEV launch-time configuration&lt;/a&gt; section below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The boot disk cannot be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-blk&lt;/span&gt;&lt;/code&gt; (due to a resource constraint
w.r.t. bounce buffers).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The VM uses machine type &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; and UEFI via OVMF.  (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; is
required in order to bind all the virtio devices to the PCIe
bridge so that they use virtio 1.0 and &lt;em&gt;not&lt;/em&gt; virtio 0.9, since
QEMU’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;iommu_platform&lt;/span&gt;&lt;/code&gt; feature is added in virtio 1.0 only.)&lt;/p&gt;
&lt;p&gt;If SEV’s requirement of a Q35 machine type cannot be satisfied by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_machine_type&lt;/span&gt;&lt;/code&gt; specified by the image (if present), or the
value specified by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt.hw_machine_type&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt;
(&lt;a class="reference external" href="https://docs.openstack.org/nova/rocky/configuration/config.html#libvirt.hw_machine_type"&gt;which is not set by default&lt;/a&gt;),
then an exception should be raised so that the build fails.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;iommu&lt;/span&gt;&lt;/code&gt; attribute is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;on&lt;/span&gt;&lt;/code&gt; for all virtio devices.  Despite
the name, this does not require the guest or host to have an IOMMU
device, but merely enables the virtio flag which indicates that
virtualized DMA should be used.  This ties into the SEV code to
handle memory encryption/decryption, and prevents IO buffers being
shared between host and guest.&lt;/p&gt;
&lt;p&gt;The DMA will go through bounce buffers, so some overhead is expected
compared to non-SEV guests.&lt;/p&gt;
&lt;p&gt;(Note: virtio-net device queues are not encrypted.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;locked/&amp;gt;&lt;/span&gt;&lt;/code&gt; element is present in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;memoryBacking&amp;gt;&lt;/span&gt;&lt;/code&gt;
section of the domain’s XML, for reasons which are explained in
the &lt;a class="reference internal" href="#memory-locking-and-accounting"&gt;Memory locking and accounting&lt;/a&gt; section below.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So for example assuming a 4GB VM:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kvm'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'x86_64'&lt;/span&gt; &lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pc-q35-2.11'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;hvm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="n"&gt;readonly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pflash'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;qemu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ovmf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;nvram&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libvirt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;qemu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nvram&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sles15&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sev&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;guest_VARS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;nvram&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'hd'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;launchSecurity&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'sev'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;cbitpos&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;cbitpos&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;reducedPhysBits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;reducedPhysBits&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mh"&gt;0x0037&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;launchSecurity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;memoryBacking&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;locked&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;memoryBacking&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'virtio'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;iommu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'on'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;memballoon&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'virtio'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;iommu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'on'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;memballoon&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'qxl'&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'65536'&lt;/span&gt; &lt;span class="n"&gt;vram&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'65536'&lt;/span&gt; &lt;span class="n"&gt;vgamem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'16384'&lt;/span&gt; &lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;  &lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For reference, &lt;a class="reference external" href="https://github.com/AMDESE/AMDSEV/"&gt;the AMDSEV GitHub repository&lt;/a&gt; provides &lt;a class="reference external" href="https://github.com/AMDESE/AMDSEV/blob/master/xmls/sample.xml"&gt;a complete example&lt;/a&gt; of a
domain’s XML definition with &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#sev"&gt;libvirt’s SEV options&lt;/a&gt; enabled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption&lt;/span&gt;&lt;/code&gt; parameter in flavor
extra specs, and a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption&lt;/span&gt;&lt;/code&gt; image property.  When
either of these is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;, it would be translated behind
the scenes into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; which would
be added to the flavor extra specs in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestSpec&lt;/span&gt;&lt;/code&gt; object.
(This change to the flavor would only affect this launch context and
not be persisted to the database.)&lt;/p&gt;
&lt;p&gt;Implementing this new parameter, which hides the implementation of
the resource inventory and allocation behind an abstraction, has
a few advantages:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;It makes it more user-friendly and oriented around the
functionality provided.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It allows us to change or extend the implementation later without
changing the user interface, for example when adding support for
similar functionality from other vendors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The translation from image property to extra spec allows us to
provide a special exception to the deliberate design decision
that image properties don’t normally facilitate placing
requirements on specific resource classes in the same way that
&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/flavors.html#extra-specs-required-resources"&gt;extra specs are allowed to&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="sev-launch-time-configuration"&gt;
&lt;h3&gt;SEV launch-time configuration&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cbitpos&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reducedPhysBits&lt;/span&gt;&lt;/code&gt; are dependent on the processor
family, and can be obtained through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sev&lt;/span&gt;&lt;/code&gt; element from &lt;a class="reference external" href="https://libvirt.org/formatdomaincaps.html#elementsSEV"&gt;the
domain capabilities&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy&lt;/span&gt;&lt;/code&gt; allows a particular SEV policy, as documented in the &lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/55766.PDF"&gt;AMD
SEV-KM API Specification&lt;/a&gt;.  Initially the policy will be hardcoded and
not modifiable by cloud tenants or cloud operators. The policy will
be:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;#define SEV_POLICY_NORM \&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;SEV_POLICY&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;SEV_POLICY_NODBG&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;SEV_POLICY_NOKS&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; \
      &lt;span class="n"&gt;SEV_POLICY_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;SEV_POLICY_SEV&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;which equates to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;0x0033&lt;/span&gt;&lt;/code&gt;.  In the future, when support is added to
QEMU and libvirt, this will permit live migration to other machines in
the same cluster &lt;a class="footnote-reference brackets" href="#id2" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; (i.e. with the same OCA cert), but doesn’t
permit other guests or the hypervisor to directly inspect memory.&lt;/p&gt;
&lt;p&gt;A future spec could be submitted to make this policy configurable via
an extra spec or image property.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/56421.pdf"&gt;SEV-ES&lt;/a&gt;
(Encrypted State, which &lt;a class="reference external" href="https://events.linuxfoundation.org/wp-content/uploads/2017/12/Extending-Secure-Encrypted-Virtualization-with-SEV-ES-Thomas-Lendacky-AMD.pdf"&gt;encrypts the guest register state to protect
it from the hypervisor&lt;/a&gt;)
is not yet ready, but may be added to this policy later.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Even though live migration is not currently supported by the
hypervisor software stack, it will be in the future.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;section id="memory-locking-and-accounting"&gt;
&lt;h4&gt;Memory locking and accounting&lt;/h4&gt;
&lt;p&gt;The presence of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;locked/&amp;gt;&lt;/span&gt;&lt;/code&gt; element in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;memoryBacking&amp;gt;&lt;/span&gt;&lt;/code&gt;
section of the domain’s XML will cause libvirt to pass &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-realtime&lt;/span&gt;
&lt;span class="pre"&gt;mlock=on&lt;/span&gt;&lt;/code&gt; to QEMU, which in turn &lt;a class="reference external" href="https://libvirt.org/git/?p=libvirt.git;a=blob;f=src/qemu/qemu_domain.c;h=ba3fff607a93533b9b47956cc2cfa70237e7c041;hb=HEAD#l10049"&gt;causes QEMU to set RLIMIT_MEMLOCK
to RLIM_INFINITY&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is needed due to a chain of factors listed immediately below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Whilst &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-realtime&lt;/span&gt; &lt;span class="pre"&gt;mlock=on&lt;/span&gt;&lt;/code&gt; will &lt;a class="reference external" href="https://github.com/qemu/qemu/blob/dafd95053611aa14dda40266857608d12ddce658/os-posix.c#L356"&gt;cause QEMU to invoke
mlockall(2)&lt;/a&gt;,
to prevent pages from swapping out, this is not sufficient to
prevent the locked pages from migrating within physical memory,
as explained in the “migrating mlocked pages” section of the
&lt;a class="reference external" href="https://www.kernel.org/doc/Documentation/vm/unevictable-lru.txt"&gt;Unevictable LRU infrastructure kernel documentation&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarly, whilst the use of hugepages would pin pages to prevent
them swapping out, it would not prevent them migrating.
Additionally &lt;a class="reference external" href="https://review.openstack.org/#/c/641994/2/specs/train/approved/amd-sev-libvirt-support.rst@167"&gt;hugepages would only allow pinning of guest RAM&lt;/a&gt;,
not the other memory chunks required by QEMU.&lt;/p&gt;
&lt;p&gt;Having said that, hugepages may still be useful for accounting, as
explained below.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All the memory pages allocated by QEMU must be pinned (not just
those allocated for guest RAM, but also video RAM, UEFI ROM /
pflash, pc.rom, isa-bios, and ACPI tables), so that they cannot
even be migrated around in physical memory, let alone swapped
out.  This is because the SEV memory encryption engine uses a
tweak such that two identical plaintext pages at a different
locations will have different ciphertexts, so swapping or moving
ciphertext of two pages will not result in the plaintext being
swapped.  In typical page migration, the pgtable tables are
updated and contents are copied from the source to the
destination.  However in the SEV case, the contents copy phase
will not provide correct results because the pages contains the
encrypted data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Therefore in order to pin the allocated pages to prevent them
migrating, QEMU’s SEV implementation will issue special
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;KVM_MEMORY_ENCRYPT_{REG,UNREG}_REGION&lt;/span&gt;&lt;/code&gt; ioctls as documented
in &lt;a class="reference external" href="https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt"&gt;the kernel’s KVM API documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These ioctls take memory regions and pin them using the kernel
APIs which ensures that those ranges are excluded from the page
move rcu list.  While pinning the pages, KVM checks
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RLIMIT_MEMLOCK&lt;/span&gt;&lt;/code&gt; to ensure that it does not blindly act upon
the request and exceed that rlimit.  If the rlimit is not large
enough then pinning the pages through this ioctl will fail.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class="simple" id="memory-reservation-solutions"&gt;
&lt;li&gt;&lt;p&gt;Initially it was planned to ensure that the rlimit was raised
sufficiently high enough by setting a hard memory limit via
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;hard_limit&amp;gt;&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;memtune&amp;gt;&lt;/span&gt;&lt;/code&gt; section of the
domain’s XML.  However, &lt;a class="reference external" href="https://review.openstack.org/#/c/641994/2/specs/train/approved/amd-sev-libvirt-support.rst@167"&gt;it was later pointed out&lt;/a&gt;
that not only it is very hard to calculate a safe upper limit
for the rlimit, and that using incorrect values will cause
virtual machines to die, but also that this could be very
wasteful because each guest would require the worst-case
(highest) upper limit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Therefore a better approach was proposed where the rlimit for
each guest is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RLIM_INFINITY&lt;/span&gt;&lt;/code&gt;, and host memory
reservation is enacted at the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/machine.slice&lt;/span&gt;&lt;/code&gt; top-level
cgroup, with all VMs placed inside that.  The latter will
protect the host OS from running out of memory due to VM
overcommit.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This problem of correct memory accounting and safe memory locking is
not specific to SEV.  Granted, SEV’s requirement to lock pages in
memory to prevent the use of swap does alter the nature of the
potential impact when oversubscription occurs, so that rather than
launching VMs and incurring heavy swapping, the VMs would fail to
launch in the first place.  In fact, arguably this “fail-fast”
approach is more desirable, since it is less likely to impact other
VMs which are already running.&lt;/p&gt;
&lt;p&gt;One suggestion proposed for more correct memory accounting was to use
hugepages for SEV guests, which are not only beneficial for
performance but also allows reuse of nova’s existing ability to track
hugepages per NUMA node and account for them in the resource tracker.
However it appears that &lt;a class="reference external" href="https://review.openstack.org/#/c/641994/2/specs/train/approved/amd-sev-libvirt-support.rst@167"&gt;this would only allow accounting of guest RAM&lt;/a&gt;,
not the other memory chunks required by QEMU.&lt;/p&gt;
&lt;p&gt;Other options include &lt;a class="reference external" href="https://docs.openstack.org/nova/rocky/configuration/config.html#DEFAULT.reserved_host_memory_mb"&gt;reserved_host_memory_mb&lt;/a&gt;, or even simply
leaving the OS distributions to take care of configuring the rlimit in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/machine.slice&lt;/span&gt;&lt;/code&gt; cgroup in their virtualization stacks as
mentioned above.&lt;/p&gt;
&lt;p&gt;However as long as operators are given clear guidance about how to
correctly mitigate these risks associated with memory reservation (as
detailed in the &lt;a class="reference internal" href="#documentation-impact"&gt;Documentation Impact&lt;/a&gt; section below), it is proposed
that obtaining a full solution should remain outside the scope of this
spec, and therefore not block it.&lt;/p&gt;
&lt;p&gt;Note that this memory pinning is expected to be a temporary
requirement; the latest firmwares already support page copying (as
documented by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COPY&lt;/span&gt;&lt;/code&gt; API in the &lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/55766.PDF"&gt;AMD SEV-KM API
Specification&lt;/a&gt;), so when the OS starts supporting the page-move or
page-migration commmand then it will no longer be needed.  However we
still need to work with older firmware and kernel combinations.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="limitations"&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;p&gt;The following limitations may be removed in the future as the
hardware, firmware, and various layer of software receive new
features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SEV-encrypted VMs cannot yet be live-migrated, or suspended,
consequently nor resumed.  As already mentioned, support is coming
in the future.  However this does mean that in the short term, usage
of SEV will have an impact on compute node maintenance, since
SEV-encrypted instances will need to be fully shut down before
migrating off an SEV host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SEV-encrypted VMs cannot contain directly accessible host devices
(PCI passthrough).  So for example mdev vGPU support will not
currently work.  However technologies based on vhost-user should
work fine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The boot disk of SEV-encrypted VMs cannot be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-blk&lt;/span&gt;&lt;/code&gt;.  Using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-scsi&lt;/span&gt;&lt;/code&gt; or SATA for the boot disk works as expected, as does
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-blk&lt;/span&gt;&lt;/code&gt; for non-boot disks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operators will initially be required to manually specify the upper
limit of SEV guests for each compute host, via the new configuration
option proposed above.  This is a short-term workaround to the
current lack of mechanism for programmatically discovering the SEV
guest limit via libvirt.&lt;/p&gt;
&lt;p&gt;This configuration option temporarily reduces the SEV detection code
proposed from essential into more of a safety check, defending
against an operator accidentally setting the config value to
non-zero on a non-SEV host.  However the detection code is &lt;a class="reference external" href="https://review.openstack.org/#/c/633855/"&gt;already
close to complete&lt;/a&gt;, and
is also still worth having long-term, since it will allow us to
remove the requirement for operators to manually specify the upper
limit as soon as it becomes possible to obtain it programmatically.
At the time of writing, &lt;a class="reference external" href="https://marc.info/?l=qemu-devel&amp;amp;m=155502702424182&amp;amp;w=2"&gt;a patch to expose the SEV guest limit in
QEMU&lt;/a&gt; is
under review, but will not be available until the 4.1.0 release at
the earliest.  &lt;a class="reference external" href="https://review.openstack.org/#/c/641994/2/specs/train/approved/amd-sev-libvirt-support.rst@527"&gt;A follow-up patch to libvirt is expected&lt;/a&gt;
which will expose it via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;domainCapabilities&amp;gt;&lt;/span&gt;&lt;/code&gt; XML mentioned
above.&lt;/p&gt;
&lt;p&gt;This config option could later be demoted to a fallback value for
cases where the limit cannot be detected programmatically, or even
removed altogether when nova’s minimum QEMU version guarantees that
it can always be detected.&lt;/p&gt;
&lt;p&gt;Deployment tools may decide to layer an additional config value set
centrally, representing a default non-zero limit for hosts where SEV
is automatically detected.  So for example if all your SEV-capable
hosts were EPYC machines with the same maximum of 15 SEV guests, you
could set that to 15 in one place and then rely on &lt;a class="reference external" href="https://review.openstack.org/#/c/633855/"&gt;the automatic
SEV detection code already proposed&lt;/a&gt; to set the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; inventory for that host to 15, without
having to set it manually on each host.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failures at VM launch-time &lt;em&gt;may&lt;/em&gt; occasionally occur in the initial
implementation, for example if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; machine type is
unavailable (although this should be rare, since &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; is nearly
11 years old), or some other required virtual component such as UEFI
is unavailable.  Future work may track availability of required
components so that failure can occur earlier, at placement time.
This potentially increases the chance of placement finding an
alternative host which can provide all the required components, and
thereby successfully booting the guest.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following limitations are expected long-term:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The number of SEV guests allowed to run concurrently will always be
limited.  &lt;a class="reference external" href="https://www.redhat.com/archives/libvir-list/2019-January/msg00652.html"&gt;On EPYC machines it will be limited to 15 guests.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The operating system running in an encrypted virtual machine must
contain SEV support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;q35&lt;/span&gt;&lt;/code&gt; machine type does not provide an IDE controller,
therefore IDE devices are not supported.  In particular this means
that nova’s libvirt driver’s current default behaviour on the x86_64
architecture of attaching the config drive as an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;iso9660&lt;/span&gt;&lt;/code&gt; IDE
CD-ROM device will not work.  There are two potential workarounds:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Change &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF.config_drive_format&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt; from &lt;a class="reference external" href="https://docs.openstack.org/nova/rocky/configuration/config.html#DEFAULT.config_drive_format"&gt;its
default value&lt;/a&gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;iso9660&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vfat&lt;/span&gt;&lt;/code&gt;.  This will result in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio&lt;/span&gt;&lt;/code&gt; being
used instead.  However this per-host setting could potentially
break images with legacy OS’s which expect the config drive to be
an IDE CD-ROM.  It would also not deal with other CD-ROM devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the (largely &lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1808868"&gt;undocumented&lt;/a&gt;)
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus&lt;/span&gt;&lt;/code&gt; image property to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio&lt;/span&gt;&lt;/code&gt;, which is
recommended as a replacement for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ide&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_scsi_model&lt;/span&gt;&lt;/code&gt;
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-scsi&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some potentially cleaner long-term solutions which require code
changes are suggested as a stretch goal in the &lt;a class="reference internal" href="#work-items"&gt;Work Items&lt;/a&gt; section
below.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the sake of eliminating any doubt, the following actions are &lt;em&gt;not&lt;/em&gt;
expected to be limited when SEV encryption is used:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Cold migration or shelve, since they power off the VM before the
operation at which point there is no encrypted memory (although this
could change since there is work underway to add support for &lt;a class="reference external" href="https://pmem.io/"&gt;PMEM&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Snapshot, since it only snapshots the disk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evacuate, since this is only initiated when the VM is assumed to be
dead or there is a good reason to kill it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attaching any volumes, as long as they do not require attaching via
an IDE bus&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use of spice / VNC / serial / RDP consoles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.suse.com/documentation/sles-12/singlehtml/article_vt_best_practices/article_vt_best_practices.html#sec.vt.best.perf.numa.vmguest"&gt;VM guest virtual NUMA (a.k.a. vNUMA)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;It has been suggested to name the resource class in a vendor-specific
way, for example &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AMD_SEV_CONTEXT&lt;/span&gt;&lt;/code&gt;.  This would avoid hard-coding
any assumptions that similar functionality from Intel (e.g. &lt;a class="reference external" href="https://en.wikichip.org/wiki/x86/tme#Multi-Key_Total_Memory_Encryption"&gt;MKTME&lt;/a&gt;)
and other vendors in the future would be subject to the same limit on
the number of guests with encrypted memory which can run concurrently.
However this raises other challenges; for example in a cloud with
mixed compute hardware from AMD and Intel both providing secure
encrypted guest memory functionality, extra specs are currently
incapable of expressing a requirement for &lt;em&gt;either&lt;/em&gt; AMD SEV hardware
&lt;em&gt;or&lt;/em&gt; Intel MKTME hardware.  Therefore there would be no way to
translate the vendor-agnostic &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption=true&lt;/span&gt;&lt;/code&gt; extra spec
parameter or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption&lt;/span&gt;&lt;/code&gt; image property into an extra spec
parameter which would achieve the desired effect.&lt;/p&gt;
&lt;p&gt;Some fundamentally different &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/amd-sev-libvirt-support.html#alternatives"&gt;approaches to SEV were originally
proposed&lt;/a&gt;
in the previous version of this spec accepted for Stein.  However
since then a significant amount of code has been both merged and
submitted for review implementing the main proposed change above, not
to mention considerable hours of discussion refining this approach.&lt;/p&gt;
&lt;p&gt;Therefore it seems very unlikely that any of those alternatives will
be used, especially considering the move from a trait-oriented design
to one oriented around a new resource class; therefore they are
omitted here.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new resource class will be used to inventory slots for SEV guests on
SEV-capable compute hosts.&lt;/p&gt;
&lt;p&gt;A new configuration option will be used (at least in the short term)
to specify the maximum number of SEV guests runnable on each compute
host.&lt;/p&gt;
&lt;p&gt;No new data objects or database schema changes will be required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None, although future work may require extending the REST API so that
users can verify the hardware’s attestation that the memory was
encrypted correctly by the firmware.  However if such an extension
would not be useful in other virt drivers across multiple CPU vendors,
it may be preferable to deliver this functionality via an independent
AMD-specific service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This change does not add or handle any secret information other than
of course data within the guest VM’s encrypted memory.  The secrets
used to implement SEV are locked inside the AMD hardware.  The
hardware random number generator uses the CTR_DRBG construct from
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/NIST_SP_800-90A"&gt;NIST SP 800-90A&lt;/a&gt;
which has not been found to be susceptible to any back doors.  It uses
AES counter mode to generate the random numbers.&lt;/p&gt;
&lt;p&gt;SEV protects data of a VM from attacks originating from outside the
VM, including the hypervisor and other VMs.  Attacks which trick the
hypervisor into reading pages from another VM will not work because
the data obtained will be encrypted with a key which is inaccessible
to the attacker and the hypervisor.  SEV protects data in caches by
tagging each cacheline with the owner of that data which prevents the
hypervisor and other VMs from reading the cached data.&lt;/p&gt;
&lt;p&gt;SEV does not protect against side-channel attacks against the VM
itself or attacks on software running in the VM.  It is important to
keep the VM up to date with patches and properly configure the
software running on the VM.&lt;/p&gt;
&lt;p&gt;This first proposed implementation provides some protection but is
notably missing the ability for the cloud user to verify the
attestation which SEV can provide using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LAUNCH_MEASURE&lt;/span&gt;&lt;/code&gt;
firmware call.  Adding such attestation ability in the future would
mean that much less trust would need to be placed in the cloud
administrator because the VM would be encrypted and integrity
protected using keys the cloud user provides to the SEV firmware over
a protected channel.  The cloud user would then know with certainty
that they are running the proper image, that the memory is indeed
encrypted, and that they are running on an authentic AMD platform with
SEV hardware and not an impostor platform setup to steal their data.
The cloud user can verify all of this before providing additional
secrets to the VM, for example storage decryption keys.  This spec is
a proposed first step in the process of obtaining the full value that
SEV can offer to prevent the cloud administrator from being able to
access the data of the cloud users.&lt;/p&gt;
&lt;p&gt;It is strongly recommended that &lt;a class="reference external" href="mailto:openstack-security%40lists.openstack.org"&gt;the OpenStack Security Group&lt;/a&gt; is kept in the loop and
given the opportunity to review each stage of work, to help ensure
that security is implemented appropriately.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;It may be desirable to access the information that the instance is
running encrypted, e.g. a billing cloud provider might want to impose
a security surcharge, whereby encrypted instances are billed
differently to unencrypted ones.  However this should require no
immediate impact on notifications, since the instance payload in the
versioned notification has the flavor along with its extra specs,
where the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource would be defined.&lt;/p&gt;
&lt;p&gt;In the case where the SEV resource is specified on the image backing
the server rather than on the flavor, the notification would just have
the image UUID in it.  The consumer could look up the image by UUID to
check for the presence of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource,
although this does open up a potential race window where image
properties could change after the instance was created.  This could be
remedied by future work which would include image properties in the
instance launch notification, or storing the image metadata in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_extra&lt;/span&gt;&lt;/code&gt; as is currently done for the flavor.  Alternatively
it may be sufficient to check for the translation to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources:MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; in the extra specs.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The end user will harness SEV through the existing mechanisms of
resources in flavor extra specs and image properties.  Later on it may
make sense to add support for scheduler hints (see the &lt;a class="reference internal" href="#future-work"&gt;Future Work&lt;/a&gt;
section below).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No performance impact on nova is anticipated.&lt;/p&gt;
&lt;p&gt;Preliminary testing indicates that the expected performance impact on
a VM of enabling SEV is moderate; a degradation of 1% to 6% has been
observed depending on the particular workload and test.  More details
can be seen in slides 4–6 of &lt;a class="reference external" href="http://events17.linuxfoundation.org/sites/events/files/slides/AMD%20SEV-ES.pdf"&gt;AMD’s presentation on SEV-ES at the
2017 Linux Security Summit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If compression is being used on swap disks then more storage may be
required because the memory of encrypted VMs will not compress to a
smaller size.&lt;/p&gt;
&lt;p&gt;Memory deduplication mechanisms such as KSM (kernel samepage merging)
would be rendered ineffective.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;In order for users to be able to use SEV, the operator will need to
perform the following steps:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Deploy SEV-capable hardware as nova compute hosts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that they have an appropriately configured software stack, so
that the various layers are all SEV ready:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;kernel &amp;gt;= 4.16&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QEMU &amp;gt;= 2.12&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libvirt &amp;gt;= 4.5&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ovmf &amp;gt;= commit 75b7aa9528bd 2018-07-06&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, a cloud administrator will need to define SEV-enabled flavors
as described above, unless it is sufficient for users to define
SEV-enabled images.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;adam.spiers&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Various developers from SUSE and AMD&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;It is expected that following sequence of extensions, or similar, will
need to be made to nova’s libvirt driver:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Add detection of host SEV capabilities as detailed above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new configuration option in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]&lt;/span&gt;&lt;/code&gt; section of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt; to set the maximum number of SEV guests allowed
per SEV compute host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource class representing
the discrete number of slots available on each SEV compute host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the libvirt driver &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update the ProviderTree object&lt;/a&gt;
with the correct inventory for the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT&lt;/span&gt;&lt;/code&gt; resource
class.  For now, set this value using the new configuration option
introduced above.  It should also take into account the results of
the SEV detection code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_AMD_SEV&lt;/span&gt;&lt;/code&gt; trait in
os-traits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.LibvirtConfigGuestSEVLaunchSecurity&lt;/span&gt;&lt;/code&gt; class
to describe the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;launchSecurity/&amp;gt;&lt;/span&gt;&lt;/code&gt; element.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.libvirt.LibvirtDriver&lt;/span&gt;&lt;/code&gt; to add the required XML
to the VM’s domain definition if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MEM_ENCRYPTION_CONTEXT=1&lt;/span&gt;&lt;/code&gt; is in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allocations&lt;/span&gt;&lt;/code&gt; dictionary passed to the libvirt driver’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spawn()&lt;/span&gt;&lt;/code&gt; method, &lt;em&gt;and&lt;/em&gt; the host is SEV-capable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine whether hugepages should be used, and if so, whether they
can help with accounting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:mem_encryption&lt;/span&gt;&lt;/code&gt; parameter in flavor
extra specs, and a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_mem_encryption&lt;/span&gt;&lt;/code&gt; image property as
described above.  Most likely these can be implemented via a new
request filter in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;request_filter.py&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since live migration between hosts is not (yet) supported for&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;SEV-encrypted instances, nor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/qemu/qemu/commit/8fa4466d77b44f4f58f3836601f31ca5e401485d"&gt;between unencrypted and SEV-encrypted states in either direction&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;prevent nova from live-migrating any SEV-encrypted instance, or
resizing onto a different compute host.  Alternatively, nova could
catch the error raised by QEMU, which would be propagated via
libvirt, and handle it appropriately.  We could build in
higher-layer checks later if it becomes a major nuisance for
operators.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarly, attempts to suspend / resume an SEV-encrypted domain are
not yet supported, and therefore should either be prevented, or the
error caught and handled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Stretch goal) Adopt one of the following suggested code changes
for reducing or even eliminating usage on x86 architectures of the
IDE bus for CD-ROM devices such as the config drive:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Simply change &lt;a class="reference external" href="https://github.com/openstack/nova/blob/396156eb13521a0e7af4488a8cd4693aa65a0da2/nova/virt/libvirt/blockinfo.py#L267"&gt;the hardcoded usage of an IDE bus for CD-ROMs on
x86&lt;/a&gt;
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scsi&lt;/span&gt;&lt;/code&gt; to be consistent with all other CPU architectures,
since it appears that the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ide&lt;/span&gt;&lt;/code&gt; only remains due to
legacy x86 code and the fact that support for other CPU
architectures was added later.  The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus=ide&lt;/span&gt;&lt;/code&gt; image
property could override this on legacy images lacking SCSI
support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto-detect the cases where the VM has no IDE controller, and
automatically switch to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scsi&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio-scsi&lt;/span&gt;&lt;/code&gt; in those
cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt; option for specifying the default
bus to use for CD-ROMs.  Then for instance the default could be
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scsi&lt;/span&gt;&lt;/code&gt; (for consistency with other CPU architectures) or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;virtio&lt;/span&gt;&lt;/code&gt;, with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus&lt;/span&gt;&lt;/code&gt; overriding this value where
needed.  This is likely to be more future-proof as the use of
very old machine types is gradually phased out, although the
downside is a small risk of breaking legacy images.&lt;/p&gt;
&lt;p&gt;If there exist clouds where such legacy x86 images are common,
the option could then be set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ide&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cdrom_bus=virtio&lt;/span&gt;&lt;/code&gt; overriding when newer machine types are
required for SEV (or any other reason).  Although this is
perhaps sufficiently unlikely as to make a new config option
overkill.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Additionally documentation should be written, as detailed in the
&lt;a class="reference internal" href="#documentation-impact"&gt;Documentation Impact&lt;/a&gt; section below.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="future-work"&gt;
&lt;h3&gt;Future work&lt;/h3&gt;
&lt;p&gt;Looking beyond Train, there is scope for several strands of additional
work for enriching nova’s SEV support:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend the &lt;a class="reference external" href="https://docs.openstack.org/nova/rocky/admin/configuration/schedulers.html#computecapabilitiesfilter"&gt;ComputeCapabilitiesFilter&lt;/a&gt;
scheduler filter to support scheduler hints, so that SEV can be
chosen to be enabled per instance, eliminating the need for
operators to configure SEV-specific flavors or images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there is sufficient demand from users, make the SEV policy
configurable via an extra spec or image property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide some mechanism by which users can access the attestation
measurement provided by SEV’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LAUNCH_MEASURE&lt;/span&gt;&lt;/code&gt; command, in order
to verify that the guest memory was encrypted correctly by the
firmware.  For example, nova’s API could be extended; however if
this cannot be done in a manner which applies across virt drivers /
CPU vendors, then it may fall outside the scope of nova and require
an alternative approach such as a separate AMD-only endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Special hardware which supports SEV for development, testing, and CI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recent versions of the hypervisor software stack which all support
SEV, as detailed in &lt;a class="reference internal" href="#other-deployer-impact"&gt;Other deployer impact&lt;/a&gt; above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UEFI bugs will need to be addressed if not done so already:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1607400"&gt;Bug #1607400 “UEFI not supported on SLES” : Bugs : OpenStack Compute (nova)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1785123"&gt;Bug #1785123 “UEFI NVRAM lost on cold migration or resize” : Bugs : OpenStack Compute (nova)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1633447"&gt;Bug #1633447 “nova stop/start or reboot –hard resets uefi nvram…” : Bugs : OpenStack Compute (nova)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fakelibvirt&lt;/span&gt;&lt;/code&gt; test driver will need adaptation to emulate
SEV-capable hardware.&lt;/p&gt;
&lt;p&gt;Corresponding unit/functional tests will need to be extended or added
to cover:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;detection of SEV-capable hardware and software, e.g. perhaps as an
extension of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.functional.libvirt.test_report_cpu_traits.LibvirtReportTraitsTests&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the use of a trait to include extra SEV-specific libvirt domain XML
configuration, e.g. within
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.tests.unit.virt.libvirt.test_config&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There will likely be issues to address due to hard-coded assumptions
oriented towards Intel CPUs either in Nova code or its tests.&lt;/p&gt;
&lt;p&gt;Tempest tests could also be included if SEV hardware is available, either
in the gate or via third-party CI.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new entry should be added in &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/support-matrix.html"&gt;the Feature Support Matrix&lt;/a&gt;,
which refers to the new trait and shows the current &lt;a class="reference internal" href="#limitations"&gt;limitations&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/rocky/admin/configuration/hypervisor-kvm.html"&gt;KVM section of the Configuration Guide&lt;/a&gt;
should be updated with details of how to set up SEV-capable
hypervisors.  It would be prudent to mention the current
&lt;a class="reference internal" href="#limitations"&gt;limitations&lt;/a&gt; here too, including the impact on config drive
configuration, compute host maintenance, the need to correctly
calculate &lt;a class="reference external" href="https://docs.openstack.org/nova/rocky/configuration/config.html#DEFAULT.reserved_host_memory_mb"&gt;reserved_host_memory_mb&lt;/a&gt; based on the expected maximum
number of SEV guests simultaneously running on the host, and the
details provided above (such as memory region sizes) which cover how
to calculate it correctly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other non-nova documentation should be updated too:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/os-traits/latest/"&gt;documentation for os-traits&lt;/a&gt; should be extended
where appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/security-guide/compute/hardening-the-virtualization-layers.html"&gt;“Hardening the virtualization layers” section of the Security
Guide&lt;/a&gt;
would be an ideal location to describe the whole process of
providing and consuming SEV functionality.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/sev"&gt;AMD SEV landing page&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://developer.amd.com/wp-content/resources/55766.PDF"&gt;AMD SEV-KM API Specification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/AMDESE/AMDSEV/"&gt;AMD SEV github repository containing examples and tools&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://events17.linuxfoundation.org/sites/events/files/slides/AMD%20SEV-ES.pdf"&gt;Slides from the 2017 Linux Security Summit describing SEV and
preliminary performance results&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://libvirt.org/formatdomain.html#sev"&gt;libvirt’s SEV options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://en.wikichip.org/wiki/x86/tme#Multi-Key_Total_Memory_Encryption"&gt;MKTME&lt;/a&gt;
- Intel’s Multi-Key Total Memory Encryption&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-approved&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>API Consistency Cleanup</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/api-consistency-cleanup.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/api-consistency-cleanup"&gt;https://blueprints.launchpad.net/nova/+spec/api-consistency-cleanup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes some of the cleanups in API for consistency
and better usage.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, there are lot of inconsistency and loose validation in APIs.
Those inconsistencies are because of v2 API compatibility.&lt;/p&gt;
&lt;p&gt;Because of loose validation for request body and query param, APIs ignore
the unknown and invalid inputs silently. This gives the impressions to user
that, requested unknown or invalid inputs are valid and taken care by Nova.
But Nova ignore all unknown or invalid inputs at API layer itself without
any warning to users.&lt;/p&gt;
&lt;p&gt;server representation is not consistent among all APIs which return the
server info in response body.
GET, PUT, REBUILD /servers APIs return the server representation (with all
server attributes). But PUT and REBUILD /servers response does not
match with GET /servers API.&lt;/p&gt;
&lt;p&gt;These are 2 examples of API inconsistency and there might be more such example
which are described in Proposed section.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an API consumer, I would like to use Nova API in more consistent way and
with strong validation for better usage.&lt;/p&gt;
&lt;p&gt;As a Developer, I would like to provide and maintain better/clean/consistent
APIs.&lt;/p&gt;
&lt;p&gt;There are maintenance benefits for client side code for parsing the API
response. For developers, maintenance can be easy only if we are able to
bump the minimum microversion in future.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to the APIs to cleanup multiple issues and
inconsistency.&lt;/p&gt;
&lt;p&gt;Proposal is to do all the mentioned cleanup in single microverison.&lt;/p&gt;
&lt;p&gt;Cleanup List:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;400 for unknown param for query param and for request body.&lt;/p&gt;
&lt;p&gt;Currently unknown param in server query param or in many other APIs request
body are ignored silently. This leads to lot of inconsistency,
one good example of this is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--deleted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--status&lt;/span&gt; &lt;span class="pre"&gt;DELETED&lt;/span&gt;&lt;/code&gt; query for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;--list&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you are non-admin then, filter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--deleted&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--status&lt;/span&gt; &lt;span class="pre"&gt;deleted&lt;/span&gt;&lt;/code&gt;
behave as 200 and 403 respectively. Both are same filter from end user
point of view but due to our implementation we return different behavior.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt; &lt;span class="pre"&gt;--deleted&lt;/span&gt;&lt;/code&gt;:
200 and it is silenlty ignored due to additionalProperty=True and for
backward compatibility API accept and ignore the invalid filters.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--deleted&lt;/span&gt;&lt;/code&gt; is invalid filter for non-admin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt; &lt;span class="pre"&gt;--status&lt;/span&gt; &lt;span class="pre"&gt;DELETED&lt;/span&gt;&lt;/code&gt; :
403. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--status&lt;/span&gt;&lt;/code&gt; is valid filter for non-admin so API does not ignore
this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We have explicit check for status=DELETED request and if requester
is non-admin then, 403.
Details discussion &lt;a class="footnote-reference brackets" href="#id4" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We can fix that by making &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties:&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; for query param
and request body of all the APIs where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties&lt;/span&gt;&lt;/code&gt; is True.
For Example &lt;a class="footnote-reference brackets" href="#id5" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and &lt;a class="footnote-reference brackets" href="#id6" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;APIs need modification:
&lt;a class="reference external" href="https://github.com/openstack/nova/search?p=1&amp;amp;q=additionalProperties%3A+True&amp;amp;unscoped_q=additionalProperties%3A+True"&gt;https://github.com/openstack/nova/search?p=1&amp;amp;q=additionalProperties%3A+True&amp;amp;unscoped_q=additionalProperties%3A+True&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making server representation always consistent among all APIs
returning the complete server representation.&lt;/p&gt;
&lt;p&gt;GET, PUT, REBUILD /servers APIs return the complete server representation
(with all server attributes). But PUT and REBUILD /servers response does not
match with GET /servers API.&lt;/p&gt;
&lt;p&gt;Difference between server representation in PUT, REBUILD from GET might
be with historic reason that PUT and REBUILD only returning the fields
in the response that could be taken on the request which modify the server,
but over time we have started returning more fields to the response to make
it consistent with GET response. That way only newly added fields in GET
response started return in PUT, REBUILD also but old fields were missed.
It end up, not keeping the original intent of PUT, REBUILD response and not
completely consistent with  GET response.&lt;/p&gt;
&lt;p&gt;There are many field which are only returned in GET API but not in PUT or
REBUILD.
Response difference which is attributes added as extensions:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-AZ:availability_zone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:hostname&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:hypervisor_hostname&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:instance_name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:kernel_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:launch_index&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:ramdisk_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:reservation_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:root_device_name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-SRV-ATTR:user_data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-STS:power_state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-STS:task_state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-EXT-STS:vm_state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-SRV-USG:launched_at&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS-SRV-USG:terminated_at&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os-extended-volumes:volumes_attached&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;APIs need modification:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;PUT /servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST /servers/{server_id}/action {rebuild}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the default return value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt; field from the empty string
to 0 (integer) in flavor APIs.&lt;/p&gt;
&lt;p&gt;Currently while creating a flavor, if you don’t set the optional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt;
property, the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt; property in the flavor API’s response
will return as an empty string.
Bug: &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1815476"&gt;https://bugs.launchpad.net/nova/+bug/1815476&lt;/a&gt;
While processing this empty string on CLI side, it is shown as blank
which is confusing and not consistent with other fields for example,
“OS-FLV-EXT-DATA:ephemeral”.
Flavor representation in server API response has the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt; default
value as 0.
Proposal is to make it consistant and return the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt; default value
as 0 (integer) in below APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;POST /flavors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /flavors/detail&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /flavors/{flavor_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /flavors/{flavor_id}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt; field always in the response of GET
hypervisors API even there are no servers on hypervisor&lt;/p&gt;
&lt;p&gt;Currently, if there are no servers on requested hypervisors then,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt; field is omitted from API response. This is not
consistent response, ideally all fields should be present in
response even with the empty value.
Proposal is to return the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt; field always in response
of below APIs. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt; field will be an empty list if there are
no servers.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-hypervisors?with_servers=True&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-hypervisors/detail?with_servers=True&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-hypervisors/{hypervisor_id}?with_servers=True&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We leave APIs as it is and use it in same way they are currently or
we can choose the set of issues from above list to fix as single go.&lt;/p&gt;
&lt;p&gt;Below cleanup already filtered out from this proposal:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Remove extensions (OS-) prefix from request and response field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix  inconsistent/incorrect response codes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;This proposal is to fix the multiple issues in APIs. I am listing
the REST API impact of each issue in same order as they are listed above.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;400 for unknown param for query param and for request body.&lt;/p&gt;
&lt;p&gt;APIs which allow unknown request and query param and ignore silently
wil be changed to return 400.
Below are the APIs which has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties:&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; and will
be modified to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;additionalProperties:&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;:
&lt;a class="reference external" href="https://github.com/openstack/nova/search?p=1&amp;amp;q=additionalProperties%3A+True&amp;amp;unscoped_q=additionalProperties%3A+True"&gt;https://github.com/openstack/nova/search?p=1&amp;amp;q=additionalProperties%3A+True&amp;amp;unscoped_q=additionalProperties%3A+True&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making server representation always consistent among all APIs&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/action&lt;/span&gt; &lt;span class="pre"&gt;{rebuild}&lt;/span&gt;&lt;/code&gt; API response
will be modified to add all the missing fields which are return by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;NOTE: new fields will be added with same name they are present in GET
/servers API response (means with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS-&lt;/span&gt;&lt;/code&gt; prefix).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the default return value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt; field from the empty string
to 0 (integer) in flavor APIs.&lt;/p&gt;
&lt;p&gt;Below APIs response will be changed to return the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swap&lt;/span&gt;&lt;/code&gt; default value
as 0 (integer):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;POST /flavors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /flavors/detail&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /flavors/{flavor_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT /flavors/{flavor_id}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt; field always in the response of GET
hypervisors API even there are no servers on hypervisor&lt;/p&gt;
&lt;p&gt;Below APIs response will be changed to return the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt;
field always in response body. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;servers&lt;/span&gt;&lt;/code&gt; field will be an
empty list if there are no servers:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /os-hypervisors?with_servers=True&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-hypervisors/detail?with_servers=True&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET /os-hypervisors/{hypervisor_id}?with_servers=True&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;The python novaclient and openstack-client will be updated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Ghanshyam Mann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Single microversion change on Nova API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests for changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python client (python-novaclient and  python-openstackclient) change&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add related unit test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response change schema test in Tempest&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Modify the api-ref to reflect the API change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Train PTG agreement: &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005824.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005824.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/nova-api-cleanup"&gt;https://etherpad.openstack.org/p/nova-api-cleanup&lt;/a&gt;
Nova API cleanup list Etherpad&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2018-07-10.log.html#t2018-07-10T14:14:18"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-nova/%23openstack-nova.2018-07-10.log.html#t2018-07-10T14:14:18&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/c5a80f4843d1f1a5289e0a3f8dbb4921b6fa44bb/nova/api/openstack/compute/schemas/servers.py#L602"&gt;https://github.com/openstack/nova/blob/c5a80f4843d1f1a5289e0a3f8dbb4921b6fa44bb/nova/api/openstack/compute/schemas/servers.py#L602&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/c6218428e9b29a2c52808ec7d27b4b21aadc0299/nova/api/openstack/compute/schemas/agents.py#L93"&gt;https://github.com/openstack/nova/blob/c6218428e9b29a2c52808ec7d27b4b21aadc0299/nova/api/openstack/compute/schemas/agents.py#L93&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions
   :header-rows: 1&lt;/span&gt;&lt;/caption&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Count quota usage from placement</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/count-quota-usage-from-placement.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/count-quota-usage-from-placement"&gt;https://blueprints.launchpad.net/nova/+spec/count-quota-usage-from-placement&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In Pike, we re-architected the quota system to count actual resource usage
instead of using reservations and tracking quota usages in a separate database
table. We’re counting resources like instances, CPU, and RAM by querying each
cell database and aggregating the results per project and per user. This
approach is problematic in the context of “handling of a down cell. If a cell
becomes unavailable, resources in its database cannot be counted and will not
be included in resource usage until the cell returns. Cells could become
unavailable if an operator is performing maintenance on a cell or if a cell
database is experiencing problems and we cannot connect to it.&lt;/p&gt;
&lt;p&gt;We can make resource usage counting for quotas resilient to temporary cell
outages by querying placement and the API database for resource usage instead
of reading separate cell databases.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When we count quota resource usage for CPU and RAM, we do so by reading
separate cell databases and aggregating the results. CPU and RAM amounts per
instance are derived from the flavor and are stored in the database as columns
in the instances table. So, each time we check quota usage against limits, we
query a count of instance ID and a sum of CPU and RAM per cell database and
aggregate them to calculate the resource usage.&lt;/p&gt;
&lt;p&gt;This approach is sensitive to temporary cell outages which may occur during
operator maintenance or if a cell database is experiencing issues and we cannot
connect to it. While a cell is unavailable, we cannot count resource usage
residing in that cell database and things would behave as though more quota is
available than should be. That is, if someone has used all of their quota and
part of it is in cell A and cell A goes offline temporarily, that person will
suddenly be able to allocate more resources than their limit (assuming cell A
returns, the person will have more resources allocated than their allowed
quota).&lt;/p&gt;
&lt;p&gt;We could take a different approach by querying the placement API and the API
database to get resource usage counts. Since placement is managing resource
allocations, it has the information we need to count resource usage for CPU and
RAM quotas. By querying placement and the API database, we can avoid reading
separate cell databases for resource usage.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Counting quota resource usage from placement would make quota behavior
consistent in the event of temporary cell database disruptions. It would be
easier for Operators to take cells offline if needed for maintenance without
concern about the possibility of quota limits being exceeded during the
maintenance. It could spare Operators the trouble of potentially having to fix
cases where quota has been exceeded during maintenance or if a cell database
connection could not be established.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We will add a new method for counting instances that queries the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_mappings&lt;/span&gt;&lt;/code&gt; table in the API database and make a separate limit check
for number of instances.&lt;/p&gt;
&lt;p&gt;The new method will contain:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;One query to the API database to get resource usage for instances. We can get
the number of instances for a project and user if we add a new column
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt; table. We already have a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; column on the table. This will allow us to count instance
mappings for a project and a user to represent the instance count.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will rename the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_instances_cores_ram_count&lt;/span&gt;&lt;/code&gt; method to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_instances_cores_ram_count_legacy&lt;/span&gt;&lt;/code&gt; that counts cores and ram from the cell
databases and is only used if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement&lt;/span&gt;&lt;/code&gt; is False or
if the data migration has not yet completed.&lt;/p&gt;
&lt;p&gt;Because there is not yet an ability to partition resource providers in
placement, in order to support deployments where multiple Nova deployments
share the same placement service, like possibly in an Edge scenario, we will
add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement&lt;/span&gt;&lt;/code&gt; config option which defaults to
False. If False, we use the legacy quota counting method for instances, cores,
and ram. If True, we use a quota counting method that calls placement. This is
a way to keep “legacy” quota counting available for the scenario of multiple
Nova deployments sharing one placement service. The config option will simply
control which counting method will be called by the pluggable quota system.
For example (pseudo-code):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quota&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count_usage_from_placement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_instances_cores_ram_count_api_db_placement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_instances_cores_ram_count_legacy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We will add a new method for counting cores and ram from placement that is used
when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement&lt;/span&gt;&lt;/code&gt; is True. This method could be called
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_cores_ram_count_placement&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The new method will contain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Up to two calls to placement to get resource usage for CPU and RAM. One call
will count usage across a project. Then, if user-scoped quota limits are
found for a resource, a second call will count usage across a project and a
user.
We can get CPU and RAM usage for a project and user by querying the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usages&lt;/span&gt;&lt;/code&gt; resource:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /usages?project_id=&amp;lt;project id&amp;gt;
GET /usages?project_id=&amp;lt;project id&amp;gt;&amp;amp;user_id=&amp;lt;user id&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative is to hold off on counting any quota usage from placement
until placement has allocation partitioning support. The problem with that is
in the meantime, the only solution we have for handling of down cells is to
implement the &lt;a class="reference external" href="https://review.openstack.org/614783"&gt;policy-driven behavior&lt;/a&gt; where an operator has to choose between
failing server create requests when a project has instances in a down cell or
allowing server create requests to potentionally exceed quota limits.&lt;/p&gt;
&lt;p&gt;Another alternative which has been discussed is, to use placement aggregates to
surround each entire Nova deployment and use that as a means to partition
placement usages. We would need to add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;aggregate=&lt;/span&gt;&lt;/code&gt; query parameter to the
placement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usages&lt;/span&gt;&lt;/code&gt; API in this case. This approach would also require some
work by either Nova or the operator to keep the placement aggregate
synchronized.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A nova_api database schema change will be required for adding the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt;
column of type String to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt; table.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;End users will see consistent quota behavior even when cell databases are
unavailable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There will be a performance impact for checking if data needs to be migrated at
the time of the quota check. The impact can be reduced by caching the results
of checks that indicate data migration has been completed for a project and
avoid a useless check per project in that case.&lt;/p&gt;
&lt;p&gt;The change involves making external REST API calls to placement instead of
doing a parallel scatter-gather to all cells. It might be slower to make the
external REST API calls if all cells are fast responding. It might be faster to
make external REST API calls if any cells are slower responding.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The addition of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; column to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt;
table will require a data migration of all existing instance mappings to
populate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; field. The migration routine would look for mappings
where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; is None and query cells by corresponding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cell_id&lt;/span&gt;&lt;/code&gt; in
the mapping. The query could filter on instance UUIDs, finding the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt;
values to populate in the mappings. This would implement the batched
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;online_data_migrations&lt;/span&gt;&lt;/code&gt; way of doing the migration.&lt;/p&gt;
&lt;p&gt;We will also heal/populate an instance mapping on-the-fly when it is accessed
during a server GET request. This would provide some data migration in the
situation where an upgrade has not run
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;online_data_migrations&lt;/span&gt;&lt;/code&gt; yet.&lt;/p&gt;
&lt;p&gt;In order to handle a live in-progress upgrade, we will need to be able to fall
back on the legacy counting method for instances, cores, and ram if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt; do not yet have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; populated (if the
operator has not yet run the data migration). We will need a way to detect that
the migration has not yet been run in order to fall back on the legacy counting
method. We could have a check such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;if&lt;/span&gt; &lt;span class="pre"&gt;exists(InstanceMapping.id)&lt;/span&gt; &lt;span class="pre"&gt;where&lt;/span&gt;
&lt;span class="pre"&gt;project_id=&amp;lt;project&lt;/span&gt; &lt;span class="pre"&gt;id&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;and&lt;/span&gt; &lt;span class="pre"&gt;user_id=None&lt;/span&gt;&lt;/code&gt;, then fall back on the legacy
counting method to query cell databases. We should cache the results of the
each migration completeness check per &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; so we avoid needlessly
checking a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id&lt;/span&gt;&lt;/code&gt; that has already been migrated every time quota is
checked.&lt;/p&gt;
&lt;p&gt;We will populate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; field even for instance mappings that are
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued_for_delete=True&lt;/span&gt;&lt;/code&gt; because such instance mappings include instances
that are &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SOFT_DELETED&lt;/span&gt;&lt;/code&gt; and these can be restored at any time in the future.
If we do not migrate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SOFT_DELETED&lt;/span&gt;&lt;/code&gt; instances with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued_for_delete=True&lt;/span&gt;&lt;/code&gt;
and they are restored in the future, their instance mappings would be
unmigrated and would prevent us being able to eventually drop the related data
migration code.&lt;/p&gt;
&lt;p&gt;The data migrations and fallback to the legacy counting method will be
temporary for Train, to be dropped in U or V with a blocker migration. That is,
you cannot pass &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;api_db&lt;/span&gt; &lt;span class="pre"&gt;sync&lt;/span&gt;&lt;/code&gt; if there are any instance mappings
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id=None&lt;/span&gt;&lt;/code&gt; to force the batched migration using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;melwitt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new column &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt; table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement an online data migration to populate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id&lt;/span&gt;&lt;/code&gt; field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_server_group_count_members_by_user&lt;/span&gt;&lt;/code&gt; quota counting method to
use only the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt; table instead of querying cell
databases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a config option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement&lt;/span&gt;&lt;/code&gt; that
defaults to False. This will be able to be deprecated when partitioning of
resource providers is available in placement and other quirks around
placement resource allocations in Nova are resolved in the future (example:
“doubling” of allocations during resizes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new method to count instances with a count of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova_api.instance_mappings&lt;/span&gt;&lt;/code&gt; filtering by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_id=&amp;lt;project_id&amp;gt;&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_id=&amp;lt;user_id&amp;gt;&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued_for_delete=False&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new count method that queries the placement API for CPU and RAM usage.
In the new count method, add a check for whether the online data migration
has been run yet and if not, fall back on the legacy count method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rename the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_instances_cores_ram_count&lt;/span&gt;&lt;/code&gt; method to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_instances_cores_ram_count_legacy&lt;/span&gt;&lt;/code&gt; and let it count only cores and ram in
the legacy way, for use if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement&lt;/span&gt;&lt;/code&gt; is False or
the data migration is not yet completed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adjust the nova-next CI job to run with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement=True&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit tests and functional tests will be included to test the new functionality.
We will also adjust one CI job (nova-next) to run with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[quota]count_usage_from_placement=True&lt;/span&gt;&lt;/code&gt; to make sure we have integration
test coverage of that path.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/cellsv2-layout.html#quota-related-quirks"&gt;documentation&lt;/a&gt; of Cells v2 caveats will be updated to update the paragraph
about the inability to correctly calculate quota usage when one or more cells
are unreachable. We will document that beginning in Train, there are new
deployment options.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;This builds upon the work done in Pike to re-architect quotas to count
resources.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/nova-specs/specs/pike/approved/cells-count-resources-to-check-quota-in-api.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/pike/approved/cells-count-resources-to-check-quota-in-api.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This may also inadvertantly fix a bug we have where if the “recheck” quota
check fails during the conductor check and the request is a multi-create, we
will have all servers fall into ERROR state for the user to clean up. Because
this change will count instance mappings for the instance count and instance
mappings have almost &lt;a class="footnote-reference brackets" href="#id2" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;*&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; the same lifetime as build requests, we should not
see the behavior of multi-create servers in ERROR state if they fail the quota
“recheck” in conductor.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1716706"&gt;https://bugs.launchpad.net/nova/+bug/1716706&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;*&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;We create build request and instance mapping in separate database
transactions, so there is a tiny window where build request can exist
without a corrensponding instance mapping.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Select CPU model from a list of CPU models</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/cpu-model-selection.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cpu-model-selection"&gt;https://blueprints.launchpad.net/nova/+spec/cpu-model-selection&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In the libvirt driver, currently we use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt;
(when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;custom&lt;/span&gt;&lt;/code&gt;) to specify the CPU model the
instance should use on this host. This could have implications on
availability of compute nodes for live migration.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the instance lands on a compute node which uses an “advanced” CPU model,
then it may only live-migrate to a few of the cluster’s compute nodes or fail
to live-migrate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The admin can configure all compute nodes use the same CPU model. But some
users may request “advanced” CPU flags for some special application (such
as video edit and scientific compute).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an admin, I would like to live-migrate instances among all compute nodes
even if there are different CPU models in the the cluster.&lt;/p&gt;
&lt;p&gt;As a user, I would like to boot an instance on a host supporting
specific CPU features and for the instance to be live-migratable to as
many other hosts as possible that also support the instance.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Rename the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model&lt;/span&gt;&lt;/code&gt; config attribute with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt;, which is
an ordered list of CPU models the host supports. It is expected that the
list is ordered so that the more common and less advanced CPU models are
listed earlier. The reported CPU feature traits will be the union of features
of all the CPU models. Mark &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model&lt;/span&gt;&lt;/code&gt; is deprecated, so existing confs
will continue to work, but will log a warning.&lt;/p&gt;
&lt;p&gt;Note that this is not add a new config attribute, this is rename exist config
attribute and extend it from singular to plural variants. Mark &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpumodel&lt;/span&gt;&lt;/code&gt; as
deprecated is to maintain capatibility with the old confs. Otherwise,
supporting both the singular and plural variants at the &lt;em&gt;same&lt;/em&gt; time (or even
after we deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model&lt;/span&gt;&lt;/code&gt;) could lead to confusion and avoidable typos.
Avoid them.&lt;/p&gt;
&lt;p&gt;End users specify CPU features they require through traits &lt;a class="footnote-reference brackets" href="#id2" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. If the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_mode&lt;/span&gt;&lt;/code&gt; is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;custom&lt;/span&gt;&lt;/code&gt;, the libvirt driver will select the first
CPU model in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt; (combined with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model_extra_flags&lt;/span&gt;&lt;/code&gt; if it is specified) that can provide the
required feature traits. This would make it more likely that the
instance could be live-migrated later on. If no CPU feature traits are
specified then the instance will be configured with the first CPU model
in the list.&lt;/p&gt;
&lt;p&gt;For example, if the end user specifies CPU features &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;avx&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;avx2&lt;/span&gt;&lt;/code&gt;
as follows:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;flavor&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_X86_AVX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_X86_AVX2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt; is configured like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;libvirt&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cpu_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;custom&lt;/span&gt;
&lt;span class="n"&gt;cpu_models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SandyBridge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;IvyBridge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Haswell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Broadwell&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Haswell&lt;/span&gt;&lt;/code&gt;, the first CPU model supporting both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;avx&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;avx2&lt;/span&gt;&lt;/code&gt;, will be chosen by libvirt.&lt;/p&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model_extra_flags&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt; specified, it should be checked
against each configured items to make sure they are compatible with host CPU.
Any incompatibility should prevent the compute service from starting and force
the user to correct the configuration.&lt;/p&gt;
&lt;p&gt;A few related points:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model&lt;/span&gt;&lt;/code&gt; are set, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_model&lt;/span&gt;&lt;/code&gt;
will be ignored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Typically, data centers only have a handful of CPU generations deployed, so
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt; is expected to contain not as many CPUs as shown in
the contrived example earlier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The value in the option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_models&lt;/span&gt;&lt;/code&gt; will be made case-insensitive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Negligible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Add some information in the config option help text indicating that the
operator should be careful to only specify models which can be fully supported
in hardware. If they specify models with CPU features that are emulated by QEMU
it could result in performance degradation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Conf: Rename &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]cpu_model&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]cpu_models&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Virt driver changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add/modify unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update release note for introducing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[libvirt]cpu_models&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/rocky/implemented/report-cpu-features-as-traits.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/rocky/implemented/report-cpu-features-as-traits.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;[2] Stein iteration of this spec:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/cpu-model-selection.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/cpu-model-selection.html&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;[3] The work in progresss spec to add more “hypervisor-literate” CPU&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;APIs to Nova – &lt;a class="reference external" href="https://review.openstack.org/#/c/645814/"&gt;https://review.openstack.org/#/c/645814/&lt;/a&gt; (“CPU
selection with hypervisor consideration”)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>CPU resource tracking</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/cpu-resources.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/cpu-resources"&gt;https://blueprints.launchpad.net/nova/+spec/cpu-resources&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We would like to both simplify the configuration of a compute node with regards
to CPU resource inventory as well as make the quantitative tracking of
dedicated CPU resources consistent with the tracking of shared CPU resources
via the placement API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The ways that CPU resources are currently tracked in Nova is overly complex
and, due to the coupling of CPU pinning with NUMA-related concepts inside the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMATopology&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopology&lt;/span&gt;&lt;/code&gt; (host) objects, difficult to
reason about in terms that are consistent with other classes of resource in
nova.&lt;/p&gt;
&lt;p&gt;Tracking of dedicated CPU resources is not done using the placement API,
therefore there is no way to view the physical processor usage in the system.
The CONF options and extra specs / image properties surrounding host CPU
inventory and guest CPU pinning are difficult to understand, and despite
efforts to document them, there are only a few individuals who even know how to
“properly” configure a compute node for hosting certain workloads.&lt;/p&gt;
&lt;p&gt;We would like to both simplify the configuration of a compute node with regards
to CPU resource inventory as well as make the quantitative tracking of
dedicated CPU resources consistent with the tracking of shared CPU resources
via the placement API.&lt;/p&gt;
&lt;section id="definitions"&gt;
&lt;h3&gt;Definitions&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;strong&gt;physical processor&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A single logical processor on the host machine that is associated with a
physical CPU core or hyperthread&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;dedicated CPU&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A physical processor that has been marked to be used for a single guest
only&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;shared CPU&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A physical processor that has been marked to be used for multiple guests&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;guest CPU&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A logical processor configured in a guest&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;VCPU&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Resource class representing a unit of CPU resources for a single guest
approximating the processing power of a single physical processor&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;PCPU&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Resource class representing an amount of dedicated CPUs for a single guest&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;CPU pinning&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The process of deciding which guest CPU should be assigned to which
dedicated CPU&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;pinset&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A set of physical processors&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;pinset string&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A specially-encoded string that indicates a set of specific physical
processors&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;NUMA-configured host system&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A host computer that has multiple physical processors arranged in a
non-uniform memory access architecture.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;guest virtual NUMA topology&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;When a guest wants its CPU resources arranged in a specific non-uniform
memory architecture layout. A guest’s virtual NUMA topology may or may not
match an underlying host system’s physical NUMA topology.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;emulator thread&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An operating system thread created by QEMU to perform certain maintenance
activities on a guest VM&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;I/O thread&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An operating system thread created by QEMU to perform disk or network I/O
on behalf of a guest VM&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;strong&gt;vCPU thread&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An operating system thread created by QEMU to execute CPU instructions on
behalf of a guest VM&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an NFV orchestration system, I want to be able to differentiate between CPU
resources that require stable performance and CPU resources that can tolerate
inconsistent performance&lt;/p&gt;
&lt;p&gt;As an edge cloud deployer, I want to specify which physical processors should
be used for dedicated CPU and which should be used for shared CPU&lt;/p&gt;
&lt;p&gt;As a VNF vendor, I wish to specify to the infrastructure whether my VNF can use
hyperthread siblings as dedicated CPUs&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="add-pcpu-resource-class"&gt;
&lt;h3&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class&lt;/h3&gt;
&lt;p&gt;In order to track dedicated CPU resources in the placement service, we need a
new resource class to differentiate guest CPU resources that are provided by a
host CPU that is shared among many guests (or many guest vCPU threads) from
guest CPU resources that are provided by a single host CPU.&lt;/p&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class will be created for this purpose. It will
represent a unit of guest CPU resources that is provided by a dedicated host
CPU. In addition, a new config option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; will be
added to track the host CPUs that will be allocated to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; inventory.
This will complement the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; config option,
which will now be used to track the host CPUs that will be allocated to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; inventory. These sets must be disjoint sets. If the two values are no
disjoint, we will fail to start with an error. If they are, any host CPUs not
included in the combined set will be considered reserved for the host.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavor.vcpus&lt;/span&gt;&lt;/code&gt; field will continue to represent the combined number of
CPUs used by the instance, be they dedicated (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;) or shared (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;).
In addition, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_allocation_ratio&lt;/span&gt;&lt;/code&gt; will apply only to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources
since overcommit for dedicated resources does not make sense.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This has significant implications for existing config options like
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;. These are discussed
&lt;a class="reference internal" href="#cpu-resources-upgrade"&gt;&lt;span class="std std-ref"&gt;below&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="add-hw-cpu-hyperthreading-trait"&gt;
&lt;h3&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;/code&gt; trait&lt;/h3&gt;
&lt;p&gt;Nova exposes hardware threads as individual “cores”, meaning a host with, for
example, two Intel Xeon E5-2620 v3 CPUs will report 24 cores - 2 sockets * 6
cores * 2 threads. However, hardware threads aren’t real CPUs as they share
share many components with each other. As a result, processes running on these
cores can suffer from contention. This can be problematic for workloads that
require no contention (think: real-time workloads).&lt;/p&gt;
&lt;p&gt;We support a feature called “CPU thread policies”, first added in &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/mitaka/implemented/virt-driver-cpu-thread-pinning.html"&gt;Mitaka&lt;/a&gt;,
which provides a way for users to control how these threads are used by
instances. One of the policies supported by this feature, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;isolate&lt;/span&gt;&lt;/code&gt;, allows
users to mark thread sibling(s) for a given CPU as reserved, avoiding resource
contention at the expense of not being able to use these cores for any other
workload. However, on a typical x86-based platform with hyperthreading enabled,
this can result in an instance consuming 2x more cores than expected, based on
the value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavor.vcpus&lt;/span&gt;&lt;/code&gt;. These untracked allocations cannot be supported
in a placement world as we need to know how many &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources to request
at scheduling time, and we can’t inflate this number (to account for the
hyperthread sibling) without being absolutely sure that &lt;em&gt;every single host&lt;/em&gt; has
hyperthreading enabled. As a result, we need to provide another way to track
whether hosts have hyperthreading or not. To this end, we will add the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;/code&gt; trait, which will be reported for hosts where
hyperthreading is detected.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This has significant implications for the existing CPU thread policies
feature. These are discussed &lt;a class="reference internal" href="#cpu-resources-upgrade"&gt;&lt;span class="std std-ref"&gt;below&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="example-host-configuration"&gt;
&lt;h3&gt;Example host configuration&lt;/h3&gt;
&lt;p&gt;Consider a compute node with a total of 24 host physical CPU cores with
hyperthreading enabled. The operator wishes to reserve 1 physical CPU core and
its thread sibling for host processing (not for guest instance use).
Furthermore, the operator wishes to use 8 host physical CPU cores and their
thread siblings for dedicated guest CPU resources. The remaining 15 host
physical CPU cores and their thread siblings will be used for shared guest vCPU
usage, with an 8:1 allocation ratio for those physical processors used for
shared guest CPU resources.&lt;/p&gt;
&lt;p&gt;The operator could configure &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.conf&lt;/span&gt;&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cpu_allocation_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cpu_dedicated_set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;
&lt;span class="n"&gt;cpu_shared_set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The virt driver will construct a provider tree containing a single resource
provider representing the compute node and report inventory of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; for this single provider accordingly:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;COMPUTE&lt;/span&gt; &lt;span class="n"&gt;NODE&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;
    &lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
        &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;min_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;max_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
        &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;allocation_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;
    &lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
        &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;min_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;max_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
        &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;allocation_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;8.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="example-flavor-configurations"&gt;
&lt;h3&gt;Example flavor configurations&lt;/h3&gt;
&lt;p&gt;Consider the following example flavor/image configurations, in increasing order
of complexity.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;A simple web application server workload requires a couple of CPU resources.
The workload does not require any dedicated CPU resources:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;VCPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create --vcpus 2 ... example-1
$ openstack flavor set --property resources:VCPU=2 example-1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, you can skip the explicit resource request and this will be
provided by default. This is the current behavior:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create --vcpus 2 ... example-1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A database server requires 8 CPU resources, and the workload needs dedicated
CPU resources to minimize effects of other workloads hosted on the same
hardware:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create --vcpus 8 ... example-2
$ openstack flavor set --property resources:PCPU=8 example-2
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, you can skip the explicit resource request and use the legacy
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; flavor extra spec instead:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create --vcpus 8 ... example-2
$ openstack flavor set --property hw:cpu_policy=dedicated example-2
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this legacy case, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; acts as an alias for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources=PCPU:${flavor.vcpus}&lt;/span&gt;&lt;/code&gt; as discussed &lt;a class="reference internal" href="#cpu-resources-upgrade"&gt;&lt;span class="std std-ref"&gt;later&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A virtual network function running a packet-core processing application
requires 8 CPU resources. The VNF specifies that the dedicated CPUs it
receives should &lt;strong&gt;not&lt;/strong&gt; be hyperthread siblings (in other words, it wants
full cores for its dedicated CPU resources):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PCPU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;forbidden&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create --vcpus 8 ... example-3
$ openstack flavor set --property resources:PCPU=8 \
    --property trait:HW_CPU_HYPERTHREADING=forbidden example-3
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, you can skip the explicit resource request and trait request
and use the legacy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_thread_policy&lt;/span&gt;&lt;/code&gt; flavor
extra specs instead:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack flavor create --vcpus 8 ... example-3
$ openstack flavor set --property hw:cpu_policy=dedicated \
    --property hw:cpu_thread_policy=isolate example-3
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this legacy case, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; acts as an alias for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources=PCPU:${flavor.vcpus}&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_thread_policy&lt;/span&gt;&lt;/code&gt; acts as an
alias for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required=!HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;/code&gt;, as discussed &lt;a class="reference internal" href="#cpu-resources-upgrade"&gt;&lt;span class="std std-ref"&gt;later&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The use of the legacy extra specs won’t give the exact same behavior as
previously as hosts that have hyperthreads will be excluded, rather than
used but have their thread siblings isolated. This is unavoidable, as
discussed &lt;a class="reference internal" href="#cpu-resources-upgrade"&gt;&lt;span class="std std-ref"&gt;below&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;It will not initially be possible to request both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; in
the same request. This functionality may be added later but such requests
will be rejected until that happens.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;You will note that the resource requests only include the total amount of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources needed by an instance. It is entirely up to
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova.virt.hardware&lt;/span&gt;&lt;/code&gt; module to &lt;strong&gt;pin&lt;/strong&gt; the guest CPUs to the host
CPUs appropriately, doing things like taking NUMA affinity into account.
The placement service will return those provider trees that match the
required amount of requested PCPU resources. But placement does not do
assignment of specific CPUs, only allocation of CPU resource amounts to
particular providers of those resources.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There’s definitely going to be some confusion around &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavor.vcpus&lt;/span&gt;&lt;/code&gt;
referring to both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource classes. To avoid this, we
could call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CPU_DEDICATED&lt;/span&gt;&lt;/code&gt; to more explicitly
indicate its purpose. However, we will continue to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resource
class to represent shared CPU resources and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; seemed a better logical
counterpart to the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resource class.&lt;/p&gt;
&lt;p&gt;Another option is to call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU_DEDICATED&lt;/span&gt;&lt;/code&gt;. This
doubles down on the idea that the term &lt;em&gt;vCPU&lt;/em&gt; refers to an instance’s CPUs (as
opposed to the host CPUs) but the name is clunky and it’s still somewhat
confusing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopology&lt;/span&gt;&lt;/code&gt; object will need to be updated to include a new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pcpuset&lt;/span&gt;&lt;/code&gt; field, which complements the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpuset&lt;/span&gt;&lt;/code&gt; field. In the
future, we may wish to rename these to e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;This proposal should actually make the CPU resource tracking easier to reason
about and understand for end users by making the inventory of both shared and
dedicated CPU resources consistent.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There should be a positive impact on performance due to the placement service
being able to perform a good portion of the work that the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; currently does. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; would be
trimmed down to only handling questions about whether a particular thread
allocation policy (tolerance of hyperthreads) could be met by a compute node.
The number of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HostInfo&lt;/span&gt;&lt;/code&gt; objects passed to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; will
have already been reduced to only those hosts which have the required number of
dedicated and shared CPU resources.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NUMATopologyFilter&lt;/span&gt;&lt;/code&gt; will still need to contain the more
esoteric and complex logic surrounding CPU pinning and understanding NUMA node
CPU amounts before compute nodes are given the ability to represent NUMA nodes
as child resource providers in provider tree.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Primarily, the impact on deployers will be documentation-related. Good
documentation needs to be provided that, like the above example flavor
configurations, shows operators what resources and traits extra specs to
configure in order to get a particular behavior and which configuration options
have changed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;span id="cpu-resources-upgrade"/&gt;&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The upgrade impact of this feature is large and while we will endeavour to
minimize impacts to the end user, there will be some disruption. The various
impacts are described below. Before reading these, it may be worth reading the
following articles which describe the current behavior of nova in various
situations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://that.guru/blog/cpu-resources/"&gt;NUMA, CPU Pinning and ‘vcpu_pin_set’&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A key point here is that the new behavior must be opt-in during Train. We
recognize that operators may need time to upgrade a critical number of compute
nodes so that they are reporting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; classes. This is reflected at
numerous points below.&lt;/p&gt;
&lt;section id="configuration-options"&gt;
&lt;h4&gt;Configuration options&lt;/h4&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;Summary&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;A user must unset the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved_host_cpus&lt;/span&gt;&lt;/code&gt;
config options and set one or both of the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt;
&lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; and new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; options.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;We will deprecate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; config option in Train. If both the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; config options
are set in Train, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; option will be ignored entirely and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; will be used instead to calculate the
amount of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources to report for each compute node. If the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; option is not set in Train, we will issue a
warning and fall back to using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; as the set of host logical
processors to allocate for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources. These CPUs &lt;strong&gt;will not&lt;/strong&gt; be
excluded from the list of host logical processors used to generate the
inventory of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources since &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; is useful for all
NUMA-based instances, not just those with pinned CPUs, and we therefore cannot
assume that these will be used exclusively by pinned instances. However, this
double reporting of inventory is not considered an issue as our long-standing
advice has been to use host aggregates to group pinned and unpinned instances.
As a result, we should not encounter the two types of instance on the same host
and either the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; inventory will be unused. If host
aggregates are not used and both pinned and unpinned instances exist in the
cloud, the user will already be seeing overallocation issues: namely, unpinned
instances do not respect the pinning constraints of pinned instances and may
float across the cores that are supposed to be “dedicated” to the pinned
instances.&lt;/p&gt;
&lt;p&gt;We will also deprecate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved_host_cpus&lt;/span&gt;&lt;/code&gt; config option in Train. If
either the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;
config options are set in Train, the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved_host_cpus&lt;/span&gt;&lt;/code&gt; config
option will be ignored and neither the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; nor &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; inventories will
have a reserved value unless explicitly set via the placement API.&lt;/p&gt;
&lt;p&gt;If neither the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;
config options are set, a warning will be logged stating that
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved_host_cpus&lt;/span&gt;&lt;/code&gt; is deprecated and that the operator should set either
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The meaning of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; will change with this feature, from
being a list of host CPUs used for emulator threads to a list of host CPUs used
for both emulator threads and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources. Note that because this option
already exists, we can’t rely on its presence to do things like ignore
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt;, as outlined previously, and must rely on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt;
&lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; instead. For this same reason, we will only use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt;
&lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; to determine the number of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; is unset. If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; is set, a warning will be logged
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; will continue to be used to calculate the number of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resource available while &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; will continue to
be used only for emulator threads.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;It is possible that there are already hosts in the wild that have
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; set but do not have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; set.
We consider this is to be exceptionally unlikely and purposefully ignore
this combination. The only reason to define &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; in
Stein or before is to use emulator thread offloading, which is used to
isolate the additional work the emulator needs to do from the work the guest
OS is doing. It is mainly required for real-time use cases. The use of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt; without &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; could result in
instance vCPUs being pinned to any host core including those listed in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;. This would defeat the whole purpose of the feature and
is very unlikely to be configured by the performance conscious users of this
feature, hence the reason for the scenario being ignored.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Finally, we will change documentation for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_allocation_ratio&lt;/span&gt;&lt;/code&gt; config
option to make it abundantly clear that this option ONLY applies to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;
and not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources&lt;/p&gt;
&lt;/section&gt;
&lt;section id="flavor-extra-specs-and-image-metadata-properties"&gt;
&lt;h4&gt;Flavor extra specs and image metadata properties&lt;/h4&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;Summary&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We will attempt to rewrite legacy flavor extra specs and image
metadata properties to the new resource types and traits, falling
back if no matches are found.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;We will alias the legacy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_thread_policy&lt;/span&gt;&lt;/code&gt; flavor
extra specs and their &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_policy&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_thread_policy&lt;/span&gt;&lt;/code&gt; image
metadata counterparts to placement requests.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy&lt;/span&gt;&lt;/code&gt; flavor extra spec and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_policy&lt;/span&gt;&lt;/code&gt; image metadata
option will be aliased to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources=(V|P)CPU:${flavor.vcpus}&lt;/span&gt;&lt;/code&gt;. For
flavors/images using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; policy, the scheduler will replace this
with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources=VCPU:${flavor.vcpus}&lt;/span&gt;&lt;/code&gt; extra spec, and for flavors/images
using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; policy, we will replace this with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources=PCPU:${flavor.vcpus}&lt;/span&gt;&lt;/code&gt; extra spec. Note that this is similar,
though not identical, to how we currently translate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Flavour.vcpus&lt;/span&gt;&lt;/code&gt; into a
placement request for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources during scheduling.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_thread_policy&lt;/span&gt;&lt;/code&gt; flavor extra spec and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_cpu_thread_policy&lt;/span&gt;&lt;/code&gt;
image metadata option will be aliased to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;/code&gt;. For
flavors/images using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;isolate&lt;/span&gt;&lt;/code&gt; policy, we will replace this with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_HYPERTHREADING=forbidden&lt;/span&gt;&lt;/code&gt;, and for flavors/images using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;require&lt;/span&gt;&lt;/code&gt; policy, we will replace this with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:HW_CPU_HYPERTHREADING=required&lt;/span&gt;&lt;/code&gt; extra spec.&lt;/p&gt;
&lt;p&gt;If the requests for placement inventory matching these requests fails, we will
revert to the legacy behavior and query placement once more. This second
request may return hosts that have been upgraded but these requests will fail
once the instance reaches the compute node as the libvirt driver will reject
it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="placement-inventory"&gt;
&lt;h4&gt;Placement inventory&lt;/h4&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;Summary&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We will automatically reshape inventory of existing instances using
pinned CPUs to use inventory of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class instead
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt;. This will happen once the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt;
&lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; config option is set.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;For existing compute nodes that have guests which use dedicated CPUs, the virt
driver will need to move inventory of existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources (which are
actually using dedicated host CPUs) to the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class.
Furthermore, existing allocations for guests on those compute nodes will need
to have their allocation records updated from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource
class.&lt;/p&gt;
&lt;p&gt;In addition, for existing compute nodes that have guests which use dedicated
CPUs &lt;strong&gt;and&lt;/strong&gt; the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;isolate&lt;/span&gt;&lt;/code&gt; CPU thread policy, the number of allocated
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources may need to be increased to account for the additional CPUs
“reserved” by the host. On an x86 host with hyperthreading enabled, this will
result in a 2x the number of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt;s being reserved (N &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources
for the instance itself and N &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; allocated to avoid another instance
using them). This will be considered legacy behavior and won’t be supported for
new instances.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="summary"&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;p&gt;The final upgrade process will look like similar to standard upgrades, though
there are some slight changes necessary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Upgrade controllers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update compute nodes in batches&lt;/p&gt;
&lt;p&gt;For compute nodes hosting pinned instances:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If set, unset &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; and set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt;. If
unset, set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; to the entire range of host
CPUs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For compute nodes hosting unpinned instances:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If set, unset &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vcpu_pin_set&lt;/span&gt;&lt;/code&gt; and set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;. If
unset, no action is necessary unless:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If set, unset &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reserved_host_cpus&lt;/span&gt;&lt;/code&gt; and set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;
to the entire range of host cores minus a number of host cores you wish to
reserve.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignees:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;stephenfin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tetsuro nakamura&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;jaypipes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cfriesen&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bauzas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resource class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_dedicated_set&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[compute]&lt;/span&gt; &lt;span class="pre"&gt;cpu_shared_set&lt;/span&gt;&lt;/code&gt;
options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify virt code to calculate the set of host CPUs that will be used for
dedicated and shared CPUs by using the above new config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the code that creates the request group from the flavor’s extra specs
and image properties to construct a request for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources when the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy=dedicated&lt;/span&gt;&lt;/code&gt; spec is found (smooth transition from legacy)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the code that currently looks at the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_thread_policy=isolate|share&lt;/span&gt;&lt;/code&gt; extra spec / image property to add a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required=HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required=!HW_CPU_HYPERTHREADING&lt;/span&gt;&lt;/code&gt; to
the request to placement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify virt code to reshape resource allocations for instances with dedicated
CPUs to consume &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PCPU&lt;/span&gt;&lt;/code&gt; resources instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VCPU&lt;/span&gt;&lt;/code&gt; resources&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Lots of functional testing for the various scenarios listed in the use cases
above will be required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Docs for admin guide about configuring flavors for dedicated and shared CPU
resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for user guide explaining difference between shared and dedicated CPU
resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docs for how the operator can configure a single host to support guests that
tolerate thread siblings as dedicated CPUs along with guests that cannot&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/543805/"&gt;Support shared and dedicated VMs on same host&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/545734/"&gt;Support shared/dedicated vCPU in one instance&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/511188/"&gt;Emulator threads policy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Originally proposed, not accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Proposed again, not accepted&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Proposed again&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Updated, based on final implementation&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Neutron SR-IOV Port Live Migration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/libvirt-neutron-sriov-livemigration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-neutron-sriov-livemigration"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-neutron-sriov-livemigration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When nova was extended to support SR-IOV by &lt;a class="footnote-reference brackets" href="#id6" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;0&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, live migration was not
directly addressed as part of the proposed changes. As a result while
live migration with SR-IOV is technically feasible, it remains unsupported
by the libvirt driver. This spec seeks to address this gap in live migration
support for the libvirt virt driver.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Live Migration with SR-IOV devices has several complicating factors.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;NUMA affinity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hardware state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SR-IOV mode&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;resource claims&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NUMA affinity is out of the scope of this spec and will be addressed
separately by &lt;a class="footnote-reference brackets" href="#id7" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The SR-IOV mode of a neutron port directly impacts how a live migration
can be done. This spec will focus on the two categories of SR-IOV primarily,
direct passthrough (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type=direct|direct-physical&lt;/span&gt;&lt;/code&gt;) and indirect
passthrough (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type=macvtap|virtio-forwarder&lt;/span&gt;&lt;/code&gt;). For simplicity, direct
mode and indirect mode are used instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vnic_type&lt;/span&gt;&lt;/code&gt; in the rest
of the spec.&lt;/p&gt;
&lt;p&gt;When a device is exposed to a guest via direct mode SR-IOV, maximum
performance is achieved at the cost of exposing the guest to the
hardware state. Since there is no standard mechanism to copy the hardware
state, direct mode SR-IOV cannot be conventionally live migrated.
This spec will provide a workaround to enable this configuration.&lt;/p&gt;
&lt;p&gt;Hardware state transfer is a property of SR-IOV live migration that cannot
be addressed by OpenStack, as such this spec does not intend to copy hardware
state. Copying hardware state requires explicit support at the hardware,
driver and hypervisor level which does not exist for SR-IOV devices.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;hardware state in this context refers to any NIC state such as
offload state or Tx/Rx queues that are implemented in hardware
which is not software programmable via the hypervisor e.g. MAC
address is not considered hardware state in this context as
libvirt/qemu can set the MAC address of an SR-IOV device via
a standard host level interface.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For SR-IOV indirect mode, the SR-IOV device is exposed via a software
mediation layer such as macvtap + kernel vhost, vhost-user or vhost-vfio.
From a guest perspective, the SR-IOV interfaces are exposed as virtual NICs
and no hardware state is observed. Indirect mode SR-IOV therefore allows
migration of guests without any workarounds.&lt;/p&gt;
&lt;p&gt;The main gap in SR-IOV live migration support today is resource claims.
As mentioned in the introduction it is technically possible to live migrate
a guest with an indirect mode SR-IOV device between two hosts today, however,
when you do, resources are not correctly claimed. By not claiming the SR-IOV
device an exception is raised after the VM has been sucessfully migrated to the
destination in the post migration cleanup.&lt;/p&gt;
&lt;p&gt;When live migrating today, migration will also fail if the PCI mapping is
required to change. Said another way, migration will only succeed if there is
a free PCI device on the destination node with the same PCI address as the
source node that is connected to the same physnet and is on the same NUMA
node.&lt;/p&gt;
&lt;p&gt;This is because of two issues. Firstly, nova does not correctly claim the
SR-IOV device on the destination node and second, nova does not modify
the guest XML to reflect the host PCI address on the destination.&lt;/p&gt;
&lt;p&gt;As a result of the above issues, SR-IOV live migration in the libvirt driver
is currently incomplete and incorrect even when the VM is successfully
moved.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a telecom operator with stateful VNF such as a vPE Router
that has a long peering time, I would like to be able to utilise
direct mode SR-IOV to meet my performance SLAs but desire the
flexibility of live migration for maintenance. To that end, as an operator,
I am willing to use a bond in the guest to a vSwitch or indirect SR-IOV
interface to facilitate migration and retain peering relationships while
understanding performance SLAs will not be met during the migration.&lt;/p&gt;
&lt;p&gt;As the provider of a cloud with a hardware offloaded vSwitch that leverages
indirect mode SR-IOV, I want to offer the performance it enables to my
customers but also desire the flexibility to be able to transparently migrate
guests without disrupting traffic to enable maintenance.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes addressing the problem statement in several steps.&lt;/p&gt;
&lt;section id="resource-claims"&gt;
&lt;h3&gt;Resource claims&lt;/h3&gt;
&lt;p&gt;Building on top of the recently added multiple port binding feature this
spec proposes to extend the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;check_can_live_migrate_destination&lt;/span&gt;&lt;/code&gt;
function to claim SR-IOV devices on the destination node via the PCI resource
tracker. If claiming fails then the partially claimed resources will be
released and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;check_can_live_migrate_destination&lt;/span&gt;&lt;/code&gt; will fail. If the claiming
succeeds the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VIFMigrateData&lt;/span&gt;&lt;/code&gt; objects in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LiveMigrateData&lt;/span&gt;&lt;/code&gt; object
corresponding to the SR-IOV devices will be updated with the destination
host PCI address. If the migration should fail after the destination resources
have been claimed they must be released in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rollback_live_migration_at_destination&lt;/span&gt;&lt;/code&gt; call. If the migration succeeds
the source host SR-IOV device will be freed in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_live_migration&lt;/span&gt;&lt;/code&gt;
(clean up source) and the state of claimed devices on the destination are
updated to allocated. By proactively updating the resouce tracker in both the
success and failure case we do not need to rely on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource&lt;/span&gt;&lt;/code&gt; periodic task to heal the allocations/claims.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="sr-iov-mode"&gt;
&lt;h3&gt;SR-IOV Mode&lt;/h3&gt;
&lt;section id="indirect-mode"&gt;
&lt;h4&gt;Indirect Mode&lt;/h4&gt;
&lt;p&gt;No other nova modifications are required for indirect mode SR-IOV
beyond those already covered in the Resouce claims sechtion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="direct-mode"&gt;
&lt;h4&gt;Direct Mode&lt;/h4&gt;
&lt;p&gt;For direct mode SR-IOV, to enable live migration the SR-IOV devices must
be first detached on the source after &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pre_live_migrate&lt;/span&gt;&lt;/code&gt; and then
reattached in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_live_migration_at_destination&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This mimics the existing suspend &lt;a class="footnote-reference brackets" href="#id8" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and resume &lt;a class="footnote-reference brackets" href="#id9" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; workflow whereby
we workaround QEMUs inability to save device state during a suspend
to disk operation.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;If you want to maintain network connectivity during the
migration, as the direct mode SR-IOV device will be detached,
a bond is required in the guest to a transparently live migratable
interface such as a vSwitch interface or a indirect mode SR-IOV
device. The recently added &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;net_fallback&lt;/span&gt;&lt;/code&gt; kernel driver is out
of scope of this spec but could also be used.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="xml-generation"&gt;
&lt;h3&gt;XML Generation&lt;/h3&gt;
&lt;p&gt;Indirect mode SR-IOV does not encode the PCI address in the libvirt XML.
The XML update logic that was introduced in the multiple port bindings
feature is sufficent to enable the indirect use case.&lt;/p&gt;
&lt;p&gt;Direct mode SR-IOV does encode the PCI address in the libvirt XML, however,
as the SR-IOV devices will be detached before migration and attached after
migration no XML updates will be required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As always we could do nothing and continue to not support live migration
with SR-IOV devices. In this case, operators would have to continue
to fall back on cold migration. As this alternative would not fix the
problem of incomplete live migration support additional documentation or
optionally a driver level check to reject live migration would be warranted
to protect operators that may not be aware of this limitation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could add a new API check to determine if an instance has an SR-IOV
port and explicitly fail to migrate in this case with a new error.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;It is expected that no data model changes should be required as the existing
VIF object in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migration_data&lt;/span&gt;&lt;/code&gt; object should be able to store the
associated PCI address info. If this is not the case a small extension to
those objects will be required for this info.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Users of direct mode SR-IOV should be aware that auto hotplugging
is not transparent to the guest in exactly the same way that
suspend is not transparent today. This will be recorded in the release
notes and live migration documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This should not significantly impact the performance of a live migration.
A minor overhead will be incurred in claiming the resource and updating the XML&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;SR-IOV live migration will be enabled if both the source and dest node support
it. If either compute node does not support this feature the migration will
be aborted by the conductor.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;This feature may aid upgrade of hosts with SR-IOV enabled
guests in the future by allowing live migration to be used
however, as that will require both the source and dest node to
support SR-IOV live migration first.
As a result, this feature, will have no impact for this release.&lt;/p&gt;
&lt;p&gt;To ensure cross version compatiblity
the conductor will validate if the source and destination nodes
support this feature following the same pattern that is used
to detect if multiple port binding is supported.&lt;/p&gt;
&lt;p&gt;When upgrading from stein to train the conductor check
will allow this feature to be used with no operator intervention
required.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;adrian.chiris&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Spec: Sean-K-Mooney&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PCI resource allocation and indirect live-migration support: Adrianc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Direct live-migration support: Sean-K-Mooney&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This spec has no dependencies but intends to collaborate with the
implementation of NUMA aware live migration &lt;a class="footnote-reference brackets" href="#id7" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that modification to the sriovnicswitch ml2 driver may
be required to support multiple port bindings. This work if needed
is out of scope of this spec and will be tracked using Neutron
RFE bugs and/or specs as required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This feature will be tested primarily via unit and functional tests,
as SR-IOV testing is not available in the gate tempest test will not
be possible. Third party CI could be implemented but that is not part
of the scope of this spec. The use of the netdevsim kernel module to allow
testing of SR-IOV without SR-IOV hardware was evaluated. While the netdevsim
kernel module does allow the creation of an SR-IOV PF netdev and the
allocation of SR-IOV VF netdevs, it does not simulate PCIe devices.
As a result in its current form the netdevsim kernel module cannot be used
to enable SR-IOV testing in the gate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operator docs will need to be updated to describe the new feature
and specify that direct mode auto-attach is not transparent to the guest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;0&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/juno/implemented/pci-passthrough-sriov.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/juno/implemented/pci-passthrough-sriov.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/599587/2/specs/stein/approved/numa-aware-live-migration.rst"&gt;https://review.openstack.org/#/c/599587/2/specs/stein/approved/numa-aware-live-migration.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/2f635fa914884c91f3b8cc78cda5154dd3b43305/nova/virt/libvirt/driver.py#L2912-L2920"&gt;https://github.com/openstack/nova/blob/2f635fa914884c91f3b8cc78cda5154dd3b43305/nova/virt/libvirt/driver.py#L2912-L2920&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/2f635fa914884c91f3b8cc78cda5154dd3b43305/nova/virt/libvirt/driver.py#L2929-L2932"&gt;https://github.com/openstack/nova/blob/2f635fa914884c91f3b8cc78cda5154dd3b43305/nova/virt/libvirt/driver.py#L2929-L2932&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id10"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Reproposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Libvirt: tenant control of qemu performance monitoring unit (vPMU)</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/libvirt-pmu-configuration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/libvirt-pmu-configuration"&gt;https://blueprints.launchpad.net/nova/+spec/libvirt-pmu-configuration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;qemu/kvm supports emulation of a vPMU to enable standard performance
monitoring tools such as &lt;a class="reference external" href="https://perf.wiki.kernel.org/index.php/Main_Page"&gt;Perf&lt;/a&gt;
to be used within a virtualisation environment. The vPMU which is available
on x86 cpus emulates the hardware PMU found on Intel processors and was
introduced in kvm in kernel 3.3.1.&lt;/p&gt;
&lt;p&gt;libvirt introduced support for vPMU control in 1.2.12
see &lt;a class="reference external" href="https://libvirt.org/formatdomain.html#elementsFeatures"&gt;https://libvirt.org/formatdomain.html#elementsFeatures&lt;/a&gt;
so this feature is available in nova minimum supported libvirt of 1.3.1.&lt;/p&gt;
&lt;p&gt;This spec aims to allow tenants to control when the vPMU is enabled.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;While kvm/qemu support for a vPMU is generally a useful feature the requirement
to collect and maintain virtual performance counter introduces additional
latency of ~10us which is about 1% of the total budget for 5G end to end
traffic processing latency. While this might seem small it is an appreciable
portion of the total latency introduced by virtulisation and is therefore
an important factor in achieving the end to end system latency target.&lt;/p&gt;
&lt;p&gt;As the provision of a vPMU is not currently controllable by an operator
or tenant directly this creates a problem for those that want to enable
or disable the vPMU to either avoid the latency overhead or rely on it
to monitor the performance of their workload.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a telecoms operator building a 5G network I wish to be able to deploy
a virtualised Radio access network (vRAN) applicance with minimal latency
impact from my virtualisation stack.&lt;/p&gt;
&lt;p&gt;As a tenant I wish to be able to monitor the performace of my application
using standard tools like perf in a virtualized environment to enable
development, tuning, and profiling of my application.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes adding a boolean image metadata key
hw_pmu=True|False and a corresponding flavor extra spec
hw:pmu=True|False to enable/disable the pmu explicitly.&lt;/p&gt;
&lt;p&gt;The default value will be unset meaning the property is not present in
either the image or flavor. This will preserve the current behavior.&lt;/p&gt;
&lt;p&gt;If the pmu property is set to true then the pmu feature element in the
libvirt xml will be set to on. Similarly if it the pmu property is set
to false the pmu feature element will be set to off.
If the pmu property is not specified no pmu element will be emitted in the
xml allowing qemu to determine if the pmu should be enabled or not.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Currently when not set the pmu is enabled/disabled based on the
cpu mode and model. If cpu_mode=host-passthough then it will be enabled;
if a custom cpu model is set it will be disabled.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In addition to the above minimum changes the libvirt driver could be modifed
to report support for a vPMU to improve scheduling. As the vPMU feature
is supported by Nova’s minimum required qemu/libvirt this would only be
useful in a heterogeneous cloud. As such the desicion to expose this
feature as a trait is left to the implementation and will be enabled as part
of &lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/image-metadata-prefiltering"&gt;https://blueprints.launchpad.net/nova/+spec/image-metadata-prefiltering&lt;/a&gt;
if desired.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;The image metadata versioned notification will be extended
to contain the newly added field.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;If the operator wants to consume this feature they will need to update
their flavors and/or images accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;The default behavior when the flavor extra_spec and image metadata
value is unset was chosen to keep backwards compatiblity on upgrade.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Extend libvirt driver config module to support the pmu element&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend libvirt dirver to enable/disable the feature based on flavor/image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;optionally enable vPMU trait.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;If we chose to enable the reporting of vPMU emulation as a trait then
the consumption of that trait would depend on the completion of
&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/image-metadata-prefiltering"&gt;https://blueprints.launchpad.net/nova/+spec/image-metadata-prefiltering&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The general feature has no dependencies&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;This will primarily be tested via unit tests of the xml generation
and flavor/image handling code. If the traits support is added
functional test using the libvirt fake driver can also be implemented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The flavor and image docs will need to be extended to document the
new extra_spec.
The Glance metadefs will also be updated to document their use and
supported values.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Support server power state update through external event</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/nova-support-instance-power-update.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-support-instance-power-update"&gt;https://blueprints.launchpad.net/nova/+spec/nova-support-instance-power-update&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec aims at providing more flexibility for operators regarding the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_sync_power_states&lt;/span&gt;&lt;/code&gt; periodic task (which aligns the server states
between the database and the hypervisor) in nova with respect to use cases for
the baremetal instances (ironic). It proposes to make this periodic power
sync’s “source of truth” configurable, depending on situations, like to allow
the physical instance to be the source of truth and make nova update its
database rather than enforcing the database state onto the physical instance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As a part of this periodic power sync between nova and ironic, when a physical
instance goes down during situations like a power outage or when the hardware
team with direct physical access to the machine does system repairs, the
instance is put into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTDOWN&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://github.com/openstack/nova/blob/d42a007425d9adb691134137e1e0b7dda356df62/nova/compute/manager.py#L7871"&gt;state by nova&lt;/a&gt; in its database since
the hypervisor is regarded as the source of truth. However when the physical
instance comes up again through non-nova-api methods like the IPMI access or
the power button, it will be put into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTDOWN&lt;/span&gt;&lt;/code&gt; state &lt;a class="reference external" href="https://github.com/openstack/nova/blob/d42a007425d9adb691134137e1e0b7dda356df62/nova/compute/manager.py#L7915"&gt;again by nova&lt;/a&gt;
since the database is regarded as the source of truth here (asynchronous).
This can cause operational inconvenience and inconsistency between
cloud operators and repair teams. Currently the only way to avoid this is by
completely disabling the power synchronisation which is not recommended.&lt;/p&gt;
&lt;p&gt;Note that ironic allows a node to be put into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maintenance&lt;/span&gt; &lt;span class="pre"&gt;mode&lt;/span&gt;&lt;/code&gt; by which
that &lt;a class="reference external" href="https://github.com/openstack/ironic/blob/84dfc151ea3091c5683b58a88e2b99302b03f5be/ironic/conductor/manager.py#L1754"&gt;node will be excluded&lt;/a&gt; from nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_sync_power_states&lt;/span&gt;&lt;/code&gt; periodic task.
This covers predictable events like scheduled repairs but does not help with
unforseen events such as power failures.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator I would like to have my physical instance’s power state as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RUNNING&lt;/span&gt;&lt;/code&gt; and not be put in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTDOWN&lt;/span&gt;&lt;/code&gt; by nova once it comes back up after
a system repair or a power outage via IPMI access or direct physical access.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To make nova hear the physical instance come up (or go down) and regard it as
the source of truth, the idea is to add a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power-update&lt;/span&gt;&lt;/code&gt; event name to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-server-external-events&lt;/span&gt;&lt;/code&gt; nova API. This event will be &lt;a class="reference external" href="https://storyboard.openstack.org/#!/story/2004969"&gt;sent by ironic&lt;/a&gt;
whenever there is a change in the power state of the down physical instance
i.e. when the physical instance comes up (or goes down) on the ironic side
and ironic trusts the hardware instead of the database as the source of
truth. Nova will be listening for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power-update&lt;/span&gt;&lt;/code&gt; event from ironic
using the existing external-events API endpoint as discussed in the
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2018-September/135122.html"&gt;nova-ironic cross project session at the Denver2018 PTG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the nova side, once such an event for a physical instance is received from
ironic, it will be routed to the virt driver. In the virt driver we will add a
new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;driver.power_update_event&lt;/span&gt;&lt;/code&gt; method which will be in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NotImplemented&lt;/span&gt;&lt;/code&gt;
state for all driver types except ironic. So if we receive a power-update for
an instance backed by a non-ironic driver we will log an error. In the ironic
driver this method will update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vm_state&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power_state&lt;/span&gt;&lt;/code&gt; fields of
that instance to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ACTIVE&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RUNNING&lt;/span&gt;&lt;/code&gt; (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;STOPPED&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SHUTDOWN&lt;/span&gt;&lt;/code&gt;)
in the nova database. Note that before routing the call to the driver the
notifications and instance actions for the power update will be handled by nova
similar to the normal start/stop operations.&lt;/p&gt;
&lt;p&gt;Even with this proposed change, depending on the order of occurrence of events
we could still have race conditions where the periodic task is already running
and it overrides the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power-update&lt;/span&gt;&lt;/code&gt; event. However this window is quite
small. To avoid the periodic task and power-update event from stepping over
each other &lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-ironic/%23openstack-ironic.2019-03-25.log.html#t2019-03-25T14:11:04"&gt;a lock can be shared&lt;/a&gt; between them.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There have been failed attempts at fixing this problem in the past like
allowing &lt;a class="reference external" href="https://review.openstack.org/#/c/190047/"&gt;admins to decide what action&lt;/a&gt; to take when the states conflict or
allowing &lt;a class="reference external" href="https://review.openstack.org/#/c/218975/"&gt;admins to reboot instances&lt;/a&gt; when the states conflict.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;A new event name will be added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;objects.InstanceExternalEvent.name&lt;/span&gt;&lt;/code&gt; enum
called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power-update&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The proposed JSON request body for the new “power-update” event is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"power-update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"server_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3df201cf-2451-44f2-8d25-a4ca826fc1f3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;target_power_state&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Definition of fields:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;name&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Name of the event. (“power-update” for this feature).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;server_uuid&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Server UUID of the physical instance whose power_state needs to be updated
in the database.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;tag&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The target_power_state values will either be “POWER_ON” (which maps to
“RUNNING” in nova) or “POWER_OFF” (which maps to “SHUTDOWN” in nova).&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The proposed JSON response body for the new “power-update” event is:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"power-update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"server_uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"3df201cf-2451-44f2-8d25-a4ca826fc1f3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;target_power_state&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Definition of fields:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;name&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Name of the event. (“power-update” for this feature).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;status&lt;/dt&gt;&lt;dd&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Event status. Possible values:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;“completed” if accepted by Nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“failed” if a failure is encountered&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/dd&gt;
&lt;dt&gt;code&lt;/dt&gt;&lt;dd&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Event result code. Possible values:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 means accepted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 means the request is missing required parameter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 means the server could not be found&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;422 means the event cannot be processed because the instance was found
to not be associated to a host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/dd&gt;
&lt;dt&gt;server_uuid&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Same value as provided in original request.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;tag&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Same value as provided in original request.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;This powering up/down of instances on the nova side will be made visible
through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/os-instance-actions&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/os-instance-actions/{request_id}&lt;/span&gt;&lt;/code&gt; API calls for the
users (by default admins and owners of the server).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;tssurya&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;wiebalck&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new external-event type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the necessary changes in the compute API and manager for the update of
the power and vm states of the instance on receiving an event from ironic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the new microversion and config option.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The client side changes needed for the events to be &lt;a class="reference external" href="https://storyboard.openstack.org/#!/story/2004969"&gt;sent by ironic&lt;/a&gt; when
the physical instance comes up or goes down.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional tests to verify the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;power-update&lt;/span&gt;&lt;/code&gt; event’s working.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the compute API reference documentation with the new power-update event.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>NUMA-aware live migration</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/numa-aware-live-migration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/numa-aware-live-migration"&gt;https://blueprints.launchpad.net/nova/+spec/numa-aware-live-migration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When an instance with NUMA characteristics is live-migrated, those
characteristics are not recalculated on the destination compute host. In the
CPU pinning case, using the source host’s pin mappings on the destination can
lead to multiple instances being pinned to the same pCPUs. In the case of
hugepage-backed instances, which are NUMA-localized, an instance needs to have
its NUMA mapping recalculated on the destination compute host during a live
migration.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In the following paragraphs the term NUMA is incorrectly used to
signify any guest characteristic that is expressed in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMATopology&lt;/span&gt;&lt;/code&gt; object, for example CPU pinning and hugepages. CPU
pinning can be achieved without a guest NUMA topology, but the two concepts
are unfortunately tightly coupled in Nova and instance pinning is not
possible without an instance NUMA topology.  For this reason, NUMA is used
as a catchall term.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec concentrates on the libvirt driver. Any higher level code
(compute manager, conductor) will be as driver agnostic as possible.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The problem can best be described with three examples.&lt;/p&gt;
&lt;p&gt;The first example is live migration with CPU pinning. An instance with a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:cpu_policy=dedicated&lt;/span&gt;&lt;/code&gt; &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/flavors.html#extra-specs-cpu-policy"&gt;extra spec&lt;/a&gt;
and pinned CPUs is live-migrated.  Its pin mappings are naively copied over to
the destination host. This creates two problems.  First, its pinned pCPUs
aren’t properly claimed on the destination.  This means that, should a second
instance with pinned CPUs land on the destination, both instances’ vCPUs could
be pinned to the same pCPUs. Second, any existing pin mappings on the
destination are ignored. If another instance already exists on the destination,
both instances’s vCPUs could be pinned to the same pCPUs. In both cases, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dedicated&lt;/span&gt;&lt;/code&gt; CPU policy is violated, potentially leading to unpredictable
performance degradation.&lt;/p&gt;
&lt;p&gt;The second example is instances with hugepages. There are two hosts, each with
two NUMA nodes and 8 1GB hugepages per node. Two identical instances are booted
on the two hosts. Their virtual NUMA topology is one virtual NUMA node and 8
1GB memory pages. They land on their respective host’s NUMA node 0, consuming
all 8 of its pages. One instance is live-migrated to the other host. The
libvirt driver enforces strict NUMA affinity and does not regenerate the
instance XML. Both instances end up on the hosts NUMA node 0, and the
live-migrated instance fails to run.&lt;/p&gt;
&lt;p&gt;The third example is an instance with a virtual NUMA topology (but without
hugepages). If an instance affined to its host’s NUMA node 2 is live migrated
to a host with only two NUMA nodes, and thus without a NUMA node 2, it will
fail to run.&lt;/p&gt;
&lt;p&gt;The first two of these examples are known bugs &lt;a class="footnote-reference brackets" href="#id10" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#id11" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a cloud administrator, I want to live migrate instances with CPU pinning
without the pin mappings overlapping on the destination compute host.&lt;/p&gt;
&lt;p&gt;As a cloud administrator, I want live migration of hugepage-backed instances to
work and for the instances to successfully run on the destination compute host.&lt;/p&gt;
&lt;p&gt;As a cloud administrator, I want live migration of instances with an explicit
NUMA topology to work and for the instances to successfully run on the
destination compute host.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There are five aspects to supporting NUMA live migration. First, the instance’s
NUMA characteristics need to be recalculated to fit on the new host. Second,
the resources that the instance will consume on the new host need to be
claimed. Third, information about the instance’s new NUMA characteristics needs
to be generated on the destination (an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMATopolgy&lt;/span&gt;&lt;/code&gt; object is not
enough, more on that later). Fourth, this information needs to be sent from
the destination to the source, in order for the source to generate the correct
XML for the instance to be able to run on the destination. Finally, the
instance’s resource claims need to “converge” to reflect the success or failure
of the live migration. If the live migration succeeded, the usage on the source
needs to be released. If it failed, the claim on the destination needs to be
rolled back.&lt;/p&gt;
&lt;section id="resource-claims"&gt;
&lt;h3&gt;Resource claims&lt;/h3&gt;
&lt;p&gt;Let’s address the resource claims aspect first. An effort has begun to support
NUMA resource providers in placement &lt;a class="footnote-reference brackets" href="#id12" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and to standardize CPU resource
tracking &lt;a class="footnote-reference brackets" href="#id13" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. However, placement can only track inventories and allocations of
quantities of resources. It does not track which specific resources are used.
Specificity is needed for NUMA live migration. Consider an instance that uses
4 dedicated CPUs in a future where the standard CPU resource tracking spec &lt;a class="footnote-reference brackets" href="#id13" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
has been implemented. During live migration, the scheduler claims those 4 CPUs
in placement on the destination. However, we need to prevent other instances
from using those specific CPUs. Therefore, in addition to claiming quantities
of CPUs in placement, we need to claim specific CPUs on the compute host. The
compute resource tracker already exists for exactly this purpose, and it will
continue to be used to claim specific resources on the destination, even in a
NUMA-enabled placement future.&lt;/p&gt;
&lt;p&gt;There is a time window between the scheduler picking a destination for the live
migration and the actual live migration RPC conversation between the two
compute hosts. Another instance could land on the destination during that time
window, using up NUMA resources that the scheduler thought were free. This race
leads to the resource claim failing on the destination. This spec proposes to
handle this claim failure using the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MigrationPreCheckError&lt;/span&gt;&lt;/code&gt;
exception mechanism, causing the scheduler to pick a new host.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="fitting-to-the-new-host"&gt;
&lt;h3&gt;Fitting to the new host&lt;/h3&gt;
&lt;p&gt;An advantage of using the resource tracker is that it forces us to use a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MoveClaim&lt;/span&gt;&lt;/code&gt;, thus giving us the instance new NUMA topology for free
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Claim._test_numa_topology&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova/compute/claims.py&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="generating-the-new-numa-information-on-the-destination"&gt;
&lt;h3&gt;Generating the new NUMA information on the destination&lt;/h3&gt;
&lt;p&gt;However, having the new instance NUMA topology in the claim isn’t enough for
the source to generate the new XML. The simplest way to generate the new XML
fom the new instance NUMA topology would be to call the libvirt driver’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_guest_numa_config&lt;/span&gt;&lt;/code&gt; method (which handily accepts an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_numa_topology&lt;/span&gt;&lt;/code&gt; as an argument). However, this needs to be done on
the destination, as it depends on the host NUMA topology.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_get_guest_numa_config&lt;/span&gt;&lt;/code&gt; returns a tuple of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtConfigObject&lt;/span&gt;&lt;/code&gt;. The
information contained therein needs to somehow be sent to the source over the
wire.&lt;/p&gt;
&lt;p&gt;The naive way would be to send the objects directly, or perhaps to call
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;to_xml&lt;/span&gt;&lt;/code&gt; and send the resulting XML blob of text. This would be unversioned,
and there would be no schema. This could cause problems in the case of, for
example, a newer libvirt driver, which has dropped support for a particular
element or attribute, talking to an older libvirt driver, which still supports
it.&lt;/p&gt;
&lt;p&gt;Because of this, and sticking to the existing OpenStack best practice of
sending oslo versionedobjects over the wire, this spec proposes encode the
necessary NUMA-related information as Nova versioned objects. These new objects
should be as virt driver independent as reasonnably possible, but as the use
case is still libvirt talking to libvirt, abstraction for the sake of
abstraction is not appropriate either.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="sending-the-new-numa-nova-objects"&gt;
&lt;h3&gt;Sending the new NUMA Nova objects&lt;/h3&gt;
&lt;p&gt;Once the superconductor has chosen and/or validated the destination host, the
relevant parts of the current live migration flow can be summarized by the
following oversimplified pseudo sequence diagram.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+-----------+&lt;/span&gt;                           &lt;span class="o"&gt;+---------+&lt;/span&gt;                        &lt;span class="o"&gt;+-------------+&lt;/span&gt; &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Conductor&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Source&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Destination&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Driver&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;                           &lt;span class="o"&gt;+---------+&lt;/span&gt;                        &lt;span class="o"&gt;+-------------+&lt;/span&gt; &lt;span class="o"&gt;+---------+&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;check_can_live_migrate_destination&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|--------------------------------------------------------------------------&amp;gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;check_can_live_migrate_source&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&amp;lt;-----------------------------------|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;migrate_data&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|-----------------------------------&amp;gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;migrate_data&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;lt;--------------------------------------------------------------------------|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;live_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrate_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|-------------------------------------&amp;gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pre_live_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrate_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|-----------------------------------&amp;gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="n"&gt;migrate_data&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&amp;lt;-----------------------------------|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;live_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrate_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|-------------------------------------------------&amp;gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                      &lt;span class="o"&gt;|&lt;/span&gt;                                    &lt;span class="o"&gt;|&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the proposed new flow, the destination compute manager asks the libvirt
driver to calculate the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtGuestConfig&lt;/span&gt;&lt;/code&gt; objects using the new
instance NUMA topology obtained from the move claim. The compute manager
converts those &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtGuestConfig&lt;/span&gt;&lt;/code&gt; objecs to the new NUMA Nova objects, and
adds them as fields to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;migrate_data&lt;/span&gt;&lt;/code&gt; object.
The latter eventually reaches the source libvirt driver, which uses it to
generate the new XML. The proposed flow is summarised in the following
diagram.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+-----------+&lt;/span&gt;                                             &lt;span class="o"&gt;+---------+&lt;/span&gt;                       &lt;span class="o"&gt;+-------------+&lt;/span&gt;                                          &lt;span class="o"&gt;+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Conductor&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                             &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Source&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;                       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Destination&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                          &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Driver&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;                                             &lt;span class="o"&gt;+---------+&lt;/span&gt;                       &lt;span class="o"&gt;+-------------+&lt;/span&gt;                                          &lt;span class="o"&gt;+---------+&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;check_can_live_migrate_destination&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|-------------------------------------------------------------------------------------------&amp;gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;check_can_live_migrate_source&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&amp;lt;----------------------------------|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;migrate_data&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|----------------------------------&amp;gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-----------------------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|-|&lt;/span&gt; &lt;span class="n"&gt;Obtain&lt;/span&gt; &lt;span class="n"&gt;new_instance_numa_topology&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;claim&lt;/span&gt;                        &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-----------------------------------+&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_get_guest_numa_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_instance_numa_topology&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;----------------------------------------------------&amp;gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                           &lt;span class="n"&gt;LibvirtConfigGuest&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&amp;lt;-----------------------------------------------------|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------------------------+&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|-|&lt;/span&gt; &lt;span class="n"&gt;Build&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;LibvirtConfigGuest&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;migrate_data&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------------------------+&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                       &lt;span class="n"&gt;migrate_data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;lt;-------------------------------------------------------------------------------------------|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;live_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrate_data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|-------------------------------------------------------&amp;gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;              &lt;span class="n"&gt;pre_live_migration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|----------------------------------&amp;gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&amp;lt;----------------------------------|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;live_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrate_data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                     &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|-----------------------------------------------------------------------------------------&amp;gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;+-----------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="n"&gt;NUMA&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;destination&lt;/span&gt; &lt;span class="o"&gt;|-|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                &lt;span class="o"&gt;+-----------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="o"&gt;|&lt;/span&gt;                                                        &lt;span class="o"&gt;|&lt;/span&gt;                                   &lt;span class="o"&gt;|&lt;/span&gt;                                                      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="claim-convergence"&gt;
&lt;h3&gt;Claim convergence&lt;/h3&gt;
&lt;p&gt;The claim object is a context manager, so it can in theory clean itself up if
any code within its context raises an unhandled exception. However, live
migration involves RPC casts between the compute hosts, making it impractical
to use the claim as a context manager. For that reason, if the live migration
fails, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;drop_move_claim&lt;/span&gt;&lt;/code&gt; needs to be called manually during the rollback to
drop the claim from the destination.  Whether to do this on the source in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rollback_live_migration&lt;/span&gt;&lt;/code&gt; or in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rollback_live_migration_at_destination&lt;/span&gt;&lt;/code&gt; is
left as an implementation detail.&lt;/p&gt;
&lt;p&gt;Similarly, if the live migration succeeds, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;drop_move_claim&lt;/span&gt;&lt;/code&gt; needs to be
called to drop the claim from the source, similar to how &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_confirm_resize&lt;/span&gt;&lt;/code&gt;
does it in the compute manager. Whether to do this in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_live_migration&lt;/span&gt;&lt;/code&gt;
on the source or in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_live_migration_at_destination&lt;/span&gt;&lt;/code&gt; is left as an
implementation detail.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Using move claims and the new instance NUMA topology calculated within
essentially dictates the rest of the implementation.&lt;/p&gt;
&lt;p&gt;When the superconductor calls the scheduler’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;select_destination&lt;/span&gt;&lt;/code&gt; method,
that call eventually ends up calling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;numa_fit_instance_to_host&lt;/span&gt;&lt;/code&gt;
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;select_destinations&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_schedule&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_consume_selected_host&lt;/span&gt;&lt;/code&gt; -&amp;gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;consume_from_request&lt;/span&gt;&lt;/code&gt; -&amp;gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_locked_consume_from_request&lt;/span&gt;&lt;/code&gt; -&amp;gt;
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;numa_fit_instance_to_host&lt;/span&gt;&lt;/code&gt;). It would be conceivable to reuse that result.
However, the claim would still calculate its own new instance NUMA topology.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;New version objects are created to transmit cell, CPU, emulator thread, and
hugepage nodeset mappings from the destination to the source. These objects are
added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LibvirtLiveMigrateData&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;In the case of a mixed N/N+1 cloud, the possibilities for the exchange of
information between the destination and the source are summarized in the
following table. In it, &lt;strong&gt;no&lt;/strong&gt; indicates that the new code is not present,
&lt;strong&gt;old path&lt;/strong&gt; indicates that the new code is present but choses to execute the
old code for backwards compatibility, and &lt;strong&gt;yes&lt;/strong&gt; indicates that the new
functionality is used.&lt;/p&gt;
&lt;table class="docutils align-default" id="id18"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Mixed N/N+1 cloud&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 10.0%"/&gt;
&lt;col style="width: 45.0%"/&gt;
&lt;col style="width: 45.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head stub"/&gt;
&lt;th class="head"&gt;&lt;p&gt;Old dest&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;New dest&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;th class="stub"&gt;&lt;p&gt;Old source&lt;/p&gt;&lt;/th&gt;
&lt;td&gt;&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;New NUMA objects from dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;New XML from source&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Initial claim on dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Claim drop for source on success&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Claim drop for dest on failure&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;New NUMA objects from dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;old path&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;New XML from source&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Initial claim on dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;old path&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Claim drop for source on success&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Claim drop for dest on failure&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;old path&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;th class="stub"&gt;&lt;p&gt;New source&lt;/p&gt;&lt;/th&gt;
&lt;td&gt;&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;New NUMA objects from dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;New XML from source&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;old path&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Initial claim on dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Claim drop for source on success&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;old path&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Claim drop for dest on failure&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;no&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;New NUMA objects from dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;New XML from source&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Initial claim on dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Claim drop for source on success&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Claim drop for dest on failure&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;notartom&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Fail live migration of instances with NUMA topology &lt;a class="footnote-reference brackets" href="#id14" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; until this spec is
fully implemented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add NUMA Nova objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add claim context to live migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calculate new NUMA topology on the destination and send it to the source&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source updates instance XML according to new NUMA topology calculated by the
destination&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The libvirt/qemu driver used in the gate does not currently support NUMA
features (though work is in progress &lt;a class="footnote-reference brackets" href="#id15" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;). Therefore, testing NUMA aware
live migration in the upstream gate would require nested virt. In addition, the
only assertable outcome of a NUMA live migration test (if it ever becomes
possible) would be that the live migration succeeded. Examining the instance
XML to assert things about its NUMA affinity or CPU pin mapping is explicitly
out of tempest’s scope. For these reasons, NUMA aware live migration is best
tested in third party CI &lt;a class="footnote-reference brackets" href="#id16" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; or other downstream test scenarios &lt;a class="footnote-reference brackets" href="#id17" id="id9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Current live migration documentation does not mention the NUMA limitations
anywhere. Therefore, a release note explaining the new NUMA capabilities of
live migration should be enough.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1496135"&gt;https://bugs.launchpad.net/nova/+bug/1496135&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1607996"&gt;https://bugs.launchpad.net/nova/+bug/1607996&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/552924/"&gt;https://review.openstack.org/#/c/552924/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id13" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id4"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/555081/"&gt;https://review.openstack.org/#/c/555081/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id14" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/611088/"&gt;https://review.openstack.org/#/c/611088/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id15" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/533077/"&gt;https://review.openstack.org/#/c/533077/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id16" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/intel-nfv-ci-tests"&gt;https://github.com/openstack/intel-nfv-ci-tests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id17" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.rdoproject.org/r/gitweb?p=openstack/whitebox-tempest-plugin.git"&gt;https://review.rdoproject.org/r/gitweb?p=openstack/whitebox-tempest-plugin.git&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;p&gt;[9] &lt;a class="reference external" href="https://review.openstack.org/#/c/244489/"&gt;https://review.openstack.org/#/c/244489/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id19"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed with modifications pertaining to claims and the exchange of
information between destination and source.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed with no modifications.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Support filtering of allocation_candidates by forbidden aggregates</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/placement-req-filter-forbidden-aggregates.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/placement-req-filter-forbidden-aggregates"&gt;https://blueprints.launchpad.net/nova/+spec/placement-req-filter-forbidden-aggregates&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to specify forbidden aggregates in the &lt;cite&gt;member_of&lt;/cite&gt;
query parameter of the &lt;cite&gt;GET /allocation_candidates&lt;/cite&gt; placement API during
scheduling.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;If flavor or image doesn’t contain any &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;required&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;forbidden&lt;/span&gt;&lt;/code&gt;
traits, then all resource providers will be eligible to be returned in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/allocation_candidates&lt;/span&gt;&lt;/code&gt; API call depending on the availability of the
requested resources. Some of the resource providers (compute host) could be
special ones like &lt;cite&gt;Licensed Windows Compute Host&lt;/cite&gt;, meaning any VM booted on
this compute host will be considered as licensed Windows image and depending
on the usage of VM operators will charge it to their end-users. As an operator,
I want to avoid booting non-windows OS images/volumes on aggregates which
contains &lt;cite&gt;Licensed Windows Compute Hosts&lt;/cite&gt;. The existing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AggregateImagePropertiesIsolationFilter&lt;/span&gt;&lt;/code&gt; scheduler filter does restricts
windows license images to windows license host aggregates but the problem is it
doesn’t exclude other images without matching metadata.&lt;/p&gt;
&lt;p&gt;Consider following example to depict the licensing use case.
Operator adds image metadata to classify images as below:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"os_distro"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"windows"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;added&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;added&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="n"&gt;aggregate&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"os_distro"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"windows"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now when user boots an instance using image 2, then this scheduler filter
allows to boot instance in host aggregate 1 which is a problem.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Some of the compute hosts are &lt;cite&gt;Licensed Windows Compute Host&lt;/cite&gt;, meaning any VMs
booted on such compute host will be considered as licensed Windows image and
depending on the usage of VM, operator will charge it to the end-users.
As an operator, I want to avoid booting non Windows OS images/volumes on
the &lt;cite&gt;Licensed Windows Compute Hosts&lt;/cite&gt; thereby enabling operators to&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Avoid wasting licensing resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Charge users correctly for their VM usage.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new placement request filter to provide isolated aggregates, and a new
config option of type boolean &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_isolated_aggregate_filtering&lt;/span&gt;&lt;/code&gt; to
enable it. Operator will set &lt;cite&gt;True&lt;/cite&gt; to enable the request filter. By default
the value will be set to &lt;cite&gt;False&lt;/cite&gt;. Operator will need to set aggregate metadata
key/value pairs &lt;cite&gt;trait:&amp;lt;trait_name&amp;gt;=required&lt;/cite&gt; with traits which they expect to
match with the &lt;cite&gt;trait:&amp;lt;trait_name&amp;gt;=required&lt;/cite&gt; set in the flavor and images of
the create server request from request_spec object. In the new request filter,
it will get the required traits set in both flavor and images from
request_spec object and compare it with the required traits set in the
aggregate metadata. If any of the traits are not matching with the aggregate
metadata, it will include that aggregate as forbidden aggregate in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member_of&lt;/span&gt;&lt;/code&gt; query parameter of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/allocation_candidates&lt;/span&gt;&lt;/code&gt; API. If there
are multiple forbidden aggregates, then the query parameter should be like:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;amp;member_of=!in:&amp;lt;agg1&amp;gt;,&amp;lt;agg2&amp;gt;,&amp;lt;agg3&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Example, how to set multiple traits to the metadata of an aggregate,&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;aggregate&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_WINDOWS_LICENSED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;aggregate&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_XYZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Operator will need to set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trait:&amp;lt;trait_name&amp;gt;=required&lt;/span&gt;&lt;/code&gt; to images for
windows OS images.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;openstack&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_WINDOWS_LICENSED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;image_uuid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example, how to enable this new placement request filter:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enable_isolated_aggregate_filtering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This placement request filter which provides isolated aggregates supersedes
existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IsolatedHostsFilter&lt;/span&gt;&lt;/code&gt; except it:-&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Relies on aggregates rather than individual hosts (which won’t scale in
large environments like a public cloud).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Relies on image properties rather than specific image IDs, which again
won’t scale.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this placement request filter in place, there is a possibility we can
deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IsolatedHostsFilter&lt;/span&gt;&lt;/code&gt; scheduler filter for reasons as stated above.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Option 1: &lt;a class="reference external" href="https://review.openstack.org/#/c/381912/17/specs/rocky/approved/strict_isolation_of_group_of_hosts_for_image.rst"&gt;Strict-isolation-group-hosts-images&lt;/a&gt; spec&lt;/p&gt;
&lt;p&gt;The main issues with this spec are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Adding a new scheduler filter which yet again depends on metadata key for
host aggregates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A compute node associated with multiple host aggregates. This is a
fundamental problem with nova host aggregates that doesn’t exist in placement
aggregates.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Option 2: &lt;a class="reference external" href="https://review.openstack.org/#/c/593475/2/specs/stein/approved/bi-directional-traits.rst"&gt;Bi-directional-enforcement-of-traits&lt;/a&gt; spec&lt;/p&gt;
&lt;p&gt;The main issue with this spec is:&lt;/p&gt;
&lt;p&gt;It’s not placement’s job to make operators have an easy life. Operators
should be required to set up their deployment’s providers with an appropriate
set of traits, put providers into appropriate aggregates, put appropriate
metadata on their own images and flavors, and configure &lt;em&gt;Nova&lt;/em&gt; with the set
of configuration options that would allow these things to be used properly.&lt;/p&gt;
&lt;p&gt;Option 3: Use &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/configuration/schedulers.html#isolatedhostsfilter"&gt;IsolatedHostsFilter&lt;/a&gt; scheduler filter&lt;/p&gt;
&lt;p&gt;It doesn’t really scale in a large public cloud with thousands of hosts and
images. Also, if you add new hosts in the system, you will need to modify the
config option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;isolated_hosts&lt;/span&gt;&lt;/code&gt; from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_scheduler&lt;/span&gt;&lt;/code&gt; section and restart
nova scheduler services.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;DB call to fetch aggregates with value &lt;cite&gt;required&lt;/cite&gt; in this
new placement request filter will marginally impact the
overall processing time of each &lt;cite&gt;select_destination&lt;/cite&gt; request.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;A new config boolean option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_isolated_aggregate_filtering&lt;/span&gt;&lt;/code&gt; will be
added in nova.conf which will be used by nova-scheduler service.
The default value of this config option will be set to false.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;enable_isolated_aggregate_filtering&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To enable request filter which provides isolated aggregates, operator should
set this config option to true.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Starting from Rocky release, nova host aggregates are mirrored in placement
service (Implemented in &lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/rocky/implemented/placement-mirror-host-aggregates.html"&gt;mirror_nova_host_aggregates&lt;/a&gt;). But if there is any
problem in mirroring, operator can sync it manually with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt;&lt;/code&gt;
command:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-manage&lt;/span&gt; &lt;span class="pre"&gt;placement&lt;/span&gt; &lt;span class="pre"&gt;sync_aggregates&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This spec will not sync traits to placement and it will not add these
traits to the compute node resource providers that belongs to the aggregates
which has metadata key=value pair with syntax &lt;cite&gt;trait:&amp;lt;trait_name&amp;gt;=required&lt;/cite&gt;.
Please refer to the &lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/nova/2019/nova.2019-06-13-14.00.log.html#l-267"&gt;Nova meeting log&lt;/a&gt; and &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-June/006950.html"&gt;Mailing thread&lt;/a&gt; where we have
mutually agreed to let operator sync these traits manually. In future,
if required, a utility tool can be developed for syncing these traits which is
outside the scope of this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;shilpa.devharakar &amp;lt;&lt;a class="reference external" href="mailto:shilpa.devharakar%40nttdata.com"&gt;shilpa&lt;span&gt;.&lt;/span&gt;devharakar&lt;span&gt;@&lt;/span&gt;nttdata&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a placement request filter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;isolate_aggregates&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resources_from_request_spec&lt;/span&gt;&lt;/code&gt; method to add isolated aggregates to
the Destination object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestGroup&lt;/span&gt;&lt;/code&gt; class &lt;cite&gt;to_querystring&lt;/cite&gt; method to generate a
&lt;cite&gt;member_of&lt;/cite&gt; query parameter to pass isolated aggregates in format
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;amp;member_of=!in:&amp;lt;agg1_uuid&amp;gt;,&amp;lt;agg2_uuid&amp;gt;,&amp;lt;agg3_uuid&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit and functional tests for the changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add releasenotes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This spec is dependent on &lt;a class="reference external" href="https://review.openstack.org/#/c/603352/4/specs/stein/approved/negative-aggregate-membership.rst"&gt;negative-aggregate-membership&lt;/a&gt; which supports
passing forbidden aggregates in the &lt;cite&gt;member_of&lt;/cite&gt; query parameter.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Add normal functional and unit testing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Add documentation to explain how to use newly added placement request filter.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Re-proposed&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Pre-filter disabled computes</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/pre-filter-disabled-computes.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/pre-filter-disabled-computes"&gt;https://blueprints.launchpad.net/nova/+spec/pre-filter-disabled-computes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to make nova report a trait to placement when a
compute service is disabled and a request filter in the scheduler which
will use that trait to filter out allocation candidates with that forbidden
trait.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In a large deployment with several thousand compute nodes, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[scheduler]/max_placement_results&lt;/span&gt;&lt;/code&gt; configuration option may be limited
such that placement returns allocation candidates which are mostly (or all)
disabled compute nodes, which can lead to a NoValidHost error during
scheduling.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I want to limit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_placement_results&lt;/span&gt;&lt;/code&gt; to improve scheduler
throughput but not suffer NoValidHost errors because placement only gives
back disabled computes.&lt;/p&gt;
&lt;p&gt;As a developer, I want to pre-filter disabled computes in placement which
should be faster (in SQL) than the legacy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeFilter&lt;/span&gt;&lt;/code&gt; running over the
results in python. In other words, I want to ask placement better questions
to get back more targeted results.&lt;/p&gt;
&lt;p&gt;As a user, I want to be able to create and resize servers without hitting
NoValidHost errors because the cloud is performing a rolling upgrade and has
disabled computes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="summary"&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Nova will start reporting a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; trait to placement
for any compute node resource provider managed by a disabled compute service
host. When the service is enabled, the trait will be removed.&lt;/p&gt;
&lt;p&gt;A scheduler &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/tag/19.0.0/nova/scheduler/request_filter.py"&gt;request filter&lt;/a&gt; will be added which will modify the RequestSpec
to filter out providers with the new trait using &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/user/flavors.html#extra-specs-forbidden-traits"&gt;forbidden trait&lt;/a&gt; filtering
syntax.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="compute-changes"&gt;
&lt;h3&gt;Compute changes&lt;/h3&gt;
&lt;p&gt;For the compute service there are two changes.&lt;/p&gt;
&lt;section id="set-host-enabled"&gt;
&lt;h4&gt;set_host_enabled&lt;/h4&gt;
&lt;p&gt;The compute service already has a &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/tag/19.0.0/nova/compute/rpcapi.py#L891"&gt;set_host_enabled&lt;/a&gt; method which is a
synchronous RPC call. Historically this was only implemented by the &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/tag/19.0.0/nova/virt/xenapi/host.py#L121"&gt;xenapi
driver&lt;/a&gt; for use with the (now deprecated) &lt;a class="reference external" href="https://developer.openstack.org/api-ref/compute/?expanded=#update-host-status"&gt;Update Host Status API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This blueprint proposes to use that compute method to generically add/remove
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; trait on the compute nodes managed by that
service (note that for ironic a compute service host can manage multiple
nodes). The trait will be managed on only the root compute node resource
provider in placement, not any nested providers.&lt;/p&gt;
&lt;p&gt;The actual implementation will be part of the &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/tag/19.0.0/nova/compute/manager.py#L419"&gt;ComputeVirtAPI&lt;/a&gt; so that
the libvirt driver has access to it when it automatically disables or enables
the compute node based on events from the hypervisor. &lt;a class="footnote-reference brackets" href="#id7" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="update-provider-tree"&gt;
&lt;h4&gt;update_provider_tree&lt;/h4&gt;
&lt;p&gt;During the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource&lt;/span&gt;&lt;/code&gt; operation which is called during
service start and periodically, the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update_provider_tree&lt;/a&gt; flow will sync
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; trait based on the current disabled status
of the service. This is useful to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Sync the trait on older disabled computes during the upgrade.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sync the trait in case the API&amp;lt;&amp;gt;compute interaction fails for some reason,
like a dropped RPC call.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="api-changes"&gt;
&lt;h3&gt;API changes&lt;/h3&gt;
&lt;p&gt;When the &lt;a class="reference external" href="https://developer.openstack.org/api-ref/compute/#compute-services-os-services"&gt;os-services&lt;/a&gt; API(s) are used to enable or disable a compute service,
the API will synchronously call the compute service via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_host_enabled&lt;/span&gt;&lt;/code&gt; RPC method to reflect the trait on the
related compute node resource providers in placement appropriately. For
example, if compute service A is disabled, the trait will be added. When
compute service A is enabled, the trait will be removed.&lt;/p&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="#upgrade-impact"&gt;Upgrade impact&lt;/a&gt; section for dealing with old computes during a
rolling upgrade.&lt;/p&gt;
&lt;section id="down-computes"&gt;
&lt;h4&gt;Down computes&lt;/h4&gt;
&lt;p&gt;It is possible to disable a down compute service since currently that disable
operation is just updating the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;services.disabled&lt;/span&gt;&lt;/code&gt; value in the cell
database. With this change, the API will have to check if the compute service
is up using the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/service-groups.html"&gt;service group API&lt;/a&gt;. If the service is down, the API will not
call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_host_enabled&lt;/span&gt;&lt;/code&gt; compute method and instead just update the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;services.disabled&lt;/span&gt;&lt;/code&gt; value in the DB as today and return. When the compute
service is restarted, the &lt;a class="reference external" href="https://docs.openstack.org/nova/latest/reference/update-provider-tree.html"&gt;update_provider_tree&lt;/a&gt; flow will sync the trait.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="scheduler-changes"&gt;
&lt;h3&gt;Scheduler changes&lt;/h3&gt;
&lt;p&gt;A request filter will be added which will modify the RequestSpec to forbid
providers with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; trait. The changes to the
RequestSpec will not be persisted.&lt;/p&gt;
&lt;p&gt;There will &lt;em&gt;not&lt;/em&gt; be a new configuration option for the request filter meaning
it will always be enabled.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In addition to filtering based on the disabled status of a node,
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ComputeFilter&lt;/span&gt;&lt;/code&gt; also performs an &lt;a class="reference external" href="https://opendev.org/openstack/nova/src/tag/19.0.0/nova/scheduler/filters/compute_filter.py#L44"&gt;is_up check&lt;/a&gt; using the
service group API. The result of the “is up” check depends on whether
or not the service was &lt;a class="reference external" href="https://developer.openstack.org/api-ref/compute/#update-forced-down"&gt;forced down&lt;/a&gt; or has not “reported in” within
some configurable interval meaning the service might be down. This
blueprint is &lt;em&gt;not&lt;/em&gt; going to try and report the up/down status of a
compute service using the new trait since it gets fairly complicated
and is more of an edge case for unexpected outages.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Rather than using a forbidden trait, we could hard-code a resource provider
aggregate UUID in nova and add/remove compute node resource providers
to/from that aggregate in placement as the service is disabled/enabled.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Pros: Aggregates may be more natural since they are a grouping of
providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cons: Using an aggregate would be harder to debug from an operational
perspective since provider aggregates do not have any name or metadata
so an operator might wonder why a certain provider is not a candidate
for scheduling but is in an aggregate they did not create (or do not
see in the nova host aggregates API). Using a trait per provider with
a clear name like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; should make it obvious
to a human that the provider is not a scheduling candidate because it
is disabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rather than using a forbidden trait or aggregate, nova could set the
reserved inventory on each provider equal to the total inventory for each
resource class on that provider, like what the ironic driver does when a
node is undergoing maintenance and should be taken out of scheduling
consideration. &lt;a class="footnote-reference brackets" href="#id8" id="id4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Pros: No new traits, can just follow the ironic driver pattern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cons: Ironic node resource providers are expected to have a single
resource class in inventory so it is easier to manage changing the
reserved value on just that one class, but for non-baremetal providers
they are reporting at least three resource classes (VCPU, MEMORY_MB and
DISK_GB) so it would be more complicated to set reserved = total on all
of those classes. Furthermore, changing the inventory is not configurable
like a request filter is.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Long-term, we could consider changing the ironic driver node maintenance
code to just set/unset the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; trait.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rather than the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-services&lt;/span&gt;&lt;/code&gt; API synchronously calling the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_host_enabled&lt;/span&gt;&lt;/code&gt; method on the compute service, the API could just
toggle the trait on the affected providers directly.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Pros: No blocking calls from the API to the compute service when changing
the disabled status of the service - although one could argue the blocking
nature proposed in the spec is advantageous so the admin gets confirmation
that the service is disabled and will be pre-filtered properly during
scheduling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cons: Potential duplication of the code that manages the trait which could
violate the principle of single responsibility.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do nothing and instead focus efforts on optimizing the performance of the
nova scheduler which is likely the root cause that large deployments need
to severely limit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_placement_results&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id9" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. However, regardless of
optimizing the scheduler (which is something we should do anyway), part of
making scheduling faster in nova is dependent on nova asking placement
more informed questions and placement providing a smaller set of allocation
candidates, i.e. filter in SQL (placement) rather than in python (nova).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None. Operators can use the &lt;a class="reference external" href="https://docs.openstack.org/osc-placement/latest/index.html"&gt;osc-placement&lt;/a&gt; CLI to view and manage provider
traits directly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;In one respect this should improve scheduler performance during an upgrade
or maintenance of a large cloud which has many disabled compute services
since placement would be returning fewer allocation candidates for the nova
scheduler to filter.&lt;/p&gt;
&lt;p&gt;On the other hand, this would add overhead to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-services&lt;/span&gt;&lt;/code&gt; API when
changing the disabled status on a compute service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;There are a few upgrade considerations for this change.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The API will check the RPC API version of the target compute service and if
it is old the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_host_enabled&lt;/span&gt;&lt;/code&gt; method will not be called. When the
compute service is upgraded and restarted, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree&lt;/span&gt;&lt;/code&gt; call
will sync the trait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Existing disabled computes need to have the trait reported
on upgrade which will happen via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_available_resource&lt;/span&gt;&lt;/code&gt; flow
(update_provider_tree) called on start of the compute after it is upgraded.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Matt Riedemann (mriedem) &amp;lt;&lt;a class="reference external" href="mailto:mriedem.os%40gmail.com"&gt;mriedem&lt;span&gt;.&lt;/span&gt;os&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make the changes to the compute service:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_host_enabled&lt;/span&gt;&lt;/code&gt; method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;update_provider_tree&lt;/span&gt;&lt;/code&gt; flow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The libvirt driver to callback to add/remove the trait when it is notified
of the hypervisor going down or up&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Plumb the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-services&lt;/span&gt;&lt;/code&gt; API to call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_host_enabled&lt;/span&gt;&lt;/code&gt; compute
service method when the disabled status changes on a compute service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a request filter which will add a forbidden trait to the
RequestSpec to filter out disabled compute node resource providers during
the GET /allocation_candidates call to placement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COMPUTE_STATUS_DISABLED&lt;/span&gt;&lt;/code&gt; trait would need to be added to the
&lt;a class="reference external" href="https://docs.openstack.org/os-traits/latest/"&gt;os-traits&lt;/a&gt; library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Unit and functional tests should be sufficient for this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new scheduler request filter will be documented in the admin docs. &lt;a class="footnote-reference brackets" href="#id10" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;section id="footnotes"&gt;
&lt;h3&gt;Footnotes&lt;/h3&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://opendev.org/openstack/nova/src/tag/19.0.0/nova/virt/libvirt/driver.py#L3802"&gt;https://opendev.org/openstack/nova/src/tag/19.0.0/nova/virt/libvirt/driver.py#L3802&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/rocky/implemented/allow-reserved-equal-total-inventory.html"&gt;https://specs.openstack.org/openstack/nova-specs/specs/rocky/implemented/allow-reserved-equal-total-inventory.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1737465"&gt;https://bugs.launchpad.net/nova/+bug/1737465&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/nova/latest/admin/configuration/schedulers.html"&gt;https://docs.openstack.org/nova/latest/admin/configuration/schedulers.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="other"&gt;
&lt;h3&gt;Other&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The original bug reported by CERN: &lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1805984"&gt;https://bugs.launchpad.net/nova/+bug/1805984&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initial proof of concept: &lt;a class="reference external" href="https://review.opendev.org/654596/"&gt;https://review.opendev.org/654596/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Train PTG mailing list mention: &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005908.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2019-May/005908.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id11"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Request Filter for Image Types</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/request-filter-image-types.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/request-filter-image-types"&gt;https://blueprints.launchpad.net/nova/+spec/request-filter-image-types&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova supports multiple hypervisor drivers with multiple potential
configurations, most of which support some subset of the allowable
image types &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; that can be uploaded to glance. Nova needs a way to
make sure that it picks compute nodes that are capable of using the
type of image requested by the user.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Nova will happily schedule instances to compute nodes with
no regard for whether or not the compute node can even read the format
that the requested image is stored in. For example, if the other
properties match, the scheduler will choose a vmware host to boot a
qcow image, which it may not be able to even read. The existing
methods for preventing this include drastic global policy &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; to
auto-convert all images to flat raw files, or to do a lot of
hand-rolled segregating of the deployment to prevent images from
landing on inappropriate compute nodes.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to have multiple hypervisors (of the same
arch) in my deployment and still be able to utilize native optimized
image formats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I want to be able to use multiple classes of compute
nodes with varying backend storage systems, some of which have image
type requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a user I want to be able to upload a native optimized image, have
it be available immediately without conversion, and be able to boot
it to a suitable host in the deployment.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Nova has the information available to be able to connect new instances
with compute nodes that can support the image requested.  There is a
gap between the services that know about image support (i.e. the
compute node and virt driver) and the services that make decisions
about where to put new instances (i.e. the scheduler). This work aims
to bridge that gap so nova can make better decisions.&lt;/p&gt;
&lt;p&gt;By exposing virt driver image format support as capabilities, and by
translating those capabilities to traits, we can report those to
placement so they are discoverable. The scheduler can examine the
format of the image during a server create or move request and ask
placement only for compute nodes that support that type (i.e. via a
new scheduler request filter). In other words, the request filter
works by mapping the image format to the appropriate trait and
including it as a required trait in the request.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative, as always, is to do nothing. Currently people solve
this in a variety of ways, from telling glance to auto-convert
everything to raw (i.e. the universal format), to hand-maintaining
aggregates and metadata to prevent images from landing in groupings of
hosts that will not be able to boot them.&lt;/p&gt;
&lt;p&gt;Another alternative could be to do this as a scheduler filter. That
would still require the virt drivers to expose their supported types,
but would have the downside of much more (inefficient) filtering of
hosts in the scheduler.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;No changes are required to Nova’s data model, nor placement’s, but
os-traits will need to gain suitable traits for the image types we
plan to expose.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Performance should not be impacted negatively, but could be improved
depending on what current hacks are in place in deployer’s systems to
provide this. Performance is definitely improved if operators are
currently requiring glance to flatten all images to raw, as after this
they would be able to leverage native optimized image formats.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;This effort will add a scheduler request filter, which (as is typical
with these) will bring a new boolean config toggle in the form of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[scheduler]/filter_hosts_by_image_type_support&lt;/span&gt;&lt;/code&gt;. The virt drivers
should be able to determine which image format capabilities to expose
from existing configuration data and thus do not need additional
configuration elements. The toggle for this could potentially be
removable in the future and just default to this behavior, if all the
virt drivers expose and continue to maintain proper image support
capability traits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;The new request filter will be disabled by default, and must remain
disabled until after an upgrade has completed so that compute nodes
will have registered their supported types. If the new filter were to
be enabled by default (or before the upgrade is complete), the
scheduler would receive no results from placement, as no nodes would
appear to support the required image formats.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;danms&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add traits to os-traits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add capabilities and trait translations to the base virt driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Augment each in-tree driver with code to expose the desired capabilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a scheduler request filter for image types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable the filter in a tempest gate job&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add words to the existing scheduler documentation about request filters&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Existing request filters are suitably covered by functional tests, and
this is no exception. We should also be able to enable this request
filter in a tempest job and have it exercise this code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Operators are impacted, and the existing scheduler documentation
around request filters will be augmented to cover this topic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Glance image allowable disk formats: &lt;a class="reference external" href="https://docs.openstack.org/image-guide/image-formats.html#disk-formats"&gt;https://docs.openstack.org/image-guide/image-formats.html#disk-formats&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Glance forced format configuration: &lt;a class="reference external" href="https://docs.openstack.org/glance/latest/configuration/glance_api.html#taskflow_executor.conversion_format"&gt;https://docs.openstack.org/glance/latest/configuration/glance_api.html#taskflow_executor.conversion_format&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Virt driver capabilities are now exposed as traits: &lt;a class="reference external" href="https://review.openstack.org/#/c/538498/"&gt;https://review.openstack.org/#/c/538498/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Train&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Show server numa topology</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/show-server-numa-topology.html</link><description>

&lt;p&gt;Add NUMA into new sub-resource &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/topology&lt;/span&gt;&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/show-server-numa-topology"&gt;https://blueprints.launchpad.net/nova/+spec/show-server-numa-topology&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is server-related NUMA information that is useful to both end user
and admin but currently there is no available API to retrieve that information.&lt;/p&gt;
&lt;p&gt;The APIs &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{id}&lt;/span&gt;&lt;/code&gt; can list extra specs which
may contain some hints about the guest NUMA topology but it is not easy to
interpret.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The admin wants to see the topology (RAM, CPU) without logging in to the
guest VM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The admin wants a unified way to get topology information, independent of
how the various guest OSes expose it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The admin wants to know the virtual-to-physical mapping for one or more
instances for the purpose of debugging, and needs to make sure the NUMA
topology is what it’s supposed to be, and is correctly mapped onto the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The end user could have all of the above abilities if the admin
allowed them by changing the default policy rules.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In Nova, the InstanceNUMATopology object contains groups of related
properties, like the amount of memory managed by a NUMA cell and the
vCPU thread to logical host processor mapping. This spec proposes
an API to present NUMA information, the cpu topology and memory page
sizes.&lt;/p&gt;
&lt;p&gt;This spec proposes a new sub-resource &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;topology&lt;/span&gt;&lt;/code&gt; to the servers API:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/topology&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This API is admin only by default, it could be exposed to users/roles by
changing the default policy rule.&lt;/p&gt;
&lt;p&gt;The topology API returns the NUMA cell information for a server, including
the memory, cpuset, siblings, CPU pinning, host NUMA node number, cpu
topology and page size.&lt;/p&gt;
&lt;p&gt;If there is no NUMA information available, the corresponding key’s value
will simply be set to None.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of putting this information into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/topology&lt;/span&gt;&lt;/code&gt;, there are two other options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;add NUMA information into the existing sub-resource &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;diagnostics&lt;/span&gt;&lt;/code&gt;:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/diagnostics&lt;/span&gt;&lt;/code&gt;
returns the NUMA information for one server. As NUMA toplogy does not change
for a given server, it’s better put under a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;topology&lt;/span&gt;&lt;/code&gt; sub-resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;put the NUMA information under &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{id}&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/detail&lt;/span&gt;&lt;/code&gt;.
This would negatively affect performance as it needs an additional database
query (via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;InstanceNUMATopology&lt;/span&gt;&lt;/code&gt; object’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_by_instance_uuid&lt;/span&gt;&lt;/code&gt;
method).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/servers/{server_id}/topology&lt;/span&gt;&lt;/code&gt; will show NUMA information with
a new microversion.&lt;/p&gt;
&lt;p&gt;The returned information for NUMA topology:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;# overall policy: TOPOLOGY % 'index&lt;/span&gt;
      &lt;span class="s2"&gt;"nodes"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
                 &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="c1"&gt;# Host Numa Node&lt;/span&gt;
                   &lt;span class="c1"&gt;# control by policy TOPOLOGY % 'index:host_info'&lt;/span&gt;
                   &lt;span class="s2"&gt;"host_numa_node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

                   &lt;span class="c1"&gt;# control by policy TOPOLOGY % 'index:host_info'&lt;/span&gt;
                   &lt;span class="c1"&gt;# 0:5 means vcpu 0 pinning to pcpu 5&lt;/span&gt;
                   &lt;span class="s2"&gt;"cpu_pinning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

                   &lt;span class="s2"&gt;"vcpu_set"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                   &lt;span class="s2"&gt;"siblings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;

                   &lt;span class="s2"&gt;"memory_mb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="p"&gt;}&lt;/span&gt;
                 &lt;span class="o"&gt;...&lt;/span&gt;
                &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# nodes&lt;/span&gt;
     &lt;span class="s2"&gt;"cpu_topology"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                         &lt;span class="c1"&gt;# toltal sockets&lt;/span&gt;
                         &lt;span class="s2"&gt;"sockets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="c1"&gt;# cores per socket&lt;/span&gt;
                         &lt;span class="s2"&gt;"cores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="c1"&gt;# thread per core&lt;/span&gt;
                         &lt;span class="s2"&gt;"threads"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
                     &lt;span class="p"&gt;}&lt;/span&gt;

     &lt;span class="s2"&gt;"pagesize_kb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The fine-grained information exposed by this API is admin only by
default, and the control policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TOPOLOGY&lt;/span&gt; &lt;span class="pre"&gt;%&lt;/span&gt; &lt;span class="pre"&gt;'index:host_info'&lt;/span&gt;&lt;/code&gt; is
used to keep host only information to admin while this API is exposed
to the end user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;topology&lt;/span&gt;&lt;/code&gt; policy, admin only by default:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;TOPOLOGY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'os_compute_api:servers:topology:&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;server_topology_policies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;BASE_POLICY_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RULE_ADMIN_API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"Show the topology data for a server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/servers/&lt;/span&gt;&lt;span class="si"&gt;{server_id}&lt;/span&gt;&lt;span class="s1"&gt;/topology'&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="c1"&gt;# control host numa node and cpu pin information&lt;/span&gt;
            &lt;span class="n"&gt;TOPOLOGY&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s1"&gt;'index:host_info'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RULE_ADMIN_API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"Show the host specific topology data for a servers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/servers/&lt;/span&gt;&lt;span class="si"&gt;{server_id}&lt;/span&gt;&lt;span class="s1"&gt;/topology'&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python novaclient and python-openstackclient should be extended to display
numa_topology information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Yongli He&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new microversion for this change.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add functional api_sample tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The API document should be changed to introduce this new feature.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Stein PTG discussion:https://etherpad.openstack.org/p/nova-ptg-stein&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mailing list discussion:
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2018-December/001070.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2018-December/001070.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="history"&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Version&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Stein&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;First Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 06 Feb 2020 00:00:00 </pubDate></item><item><title>Support delete_on_termination in server attach volume</title><link>https://specs.openstack.org/openstack/nova-specs/specs/train/implemented/support-delete-on-termination-in-server-attach-volume.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/support-delete-on-termination-in-server-attach-volume"&gt;https://blueprints.launchpad.net/nova/+spec/support-delete-on-termination-in-server-attach-volume&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint proposes to support passing delete_on_termination during
volume attach so the attached volume can be deleted when the server is
deleted.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, nova already supports the volume attach API, but it is not
possible to configure whether the data volumes can be deleted when the
instance is destroyed while the volume is being attached. This is a bit
awkward when configuring the server to handle the data volume in the
destroy instance.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;In large scale environment, lots of resources were created in system, and
sometimes an instance needs to be attached with more data volumes.
Therefore, the user needs to set the processing mode of the attached volume
for each instance. When destroying the instance, the data volume can be
deleted together, the invalid data is cleared, and the storage space is
released.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new microversion to volume attach API to support configuring whether
to delete the data volume when the instance is destroyed.&lt;/p&gt;
&lt;p&gt;In the same microversion, add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; to the GET responses
when showing attached volumes.&lt;/p&gt;
&lt;p&gt;See the &lt;a class="reference internal" href="#rest-api-impact"&gt;REST API impact&lt;/a&gt; section for details.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The user cleans up the data volumes manually after deleting the server as they
would have to do today.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;URL: /v2.1/servers/{server_id}/os-volume_attachments&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request method: POST (attach volume)&lt;/p&gt;
&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; parameter to the request body with the
same semantics/schema as the initial server create
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;block_device_mapping_v2&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f804"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The default value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; field is &lt;strong&gt;False&lt;/strong&gt; if not
specified.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request method: GET (list volume attachments)&lt;/p&gt;
&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; field to the response payload for attached
volumes.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f803"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fb6077e6-c10d-4e81-87fa-cb0f8c103051"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f803"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f804"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fb6077e6-c10d-4e81-87fa-cb0f8c103051"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f804"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;URL: /servers/{server_id}/os-volume_attachments/{volume_id}&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Request method: GET (show volume attachment)&lt;/p&gt;
&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; field to the response payload for attached
volume.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"volumeAttachment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/dev/sdc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f804"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"serverId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fb6077e6-c10d-4e81-87fa-cb0f8c103051"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"volumeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a26887c6-c47b-4654-abb5-dfadf7d3f804"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"delete_on_termination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;PUT /servers/{server_id}/os-volume_attachments/{volume_id} is not
part of this proposed change since that API today is only implemented
for the “swap volume” operation which is only implemented by the
libvirt driver. &lt;a class="footnote-reference brackets" href="#id2" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; Modifying the PUT API is out of scope for this
spec. If a user wishes to change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; value
of a non-root attached volume, they can do so by detaching and
re-attaching the volume with the updated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt;
value.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;python-novaclient and python-openstack client will need to be updated to
support the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_on_termination&lt;/span&gt;&lt;/code&gt; parameter when attaching a volume
and listing/showing attached volumes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="upgrade-impact"&gt;
&lt;h3&gt;Upgrade impact&lt;/h3&gt;
&lt;p&gt;Depending on implementation there should be no upgrade impact. Today when a
volume is attached to a non-shelved-offloaded server, the BlockDeviceMapping
record is created in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova-comput